diff --git a/config/alfresco/bootstrap-context.xml b/config/alfresco/bootstrap-context.xml index 8cedc495d4..7b55e9dd32 100644 --- a/config/alfresco/bootstrap-context.xml +++ b/config/alfresco/bootstrap-context.xml @@ -436,6 +436,9 @@ + + + diff --git a/config/alfresco/content-services-context.xml b/config/alfresco/content-services-context.xml index b21121a42e..40f1d8af08 100644 --- a/config/alfresco/content-services-context.xml +++ b/config/alfresco/content-services-context.xml @@ -297,9 +297,6 @@ - - - @@ -315,6 +312,33 @@ + + + + + + + + + + + + + org.alfresco.repo.content.transform.TransformerConfig + + + + + + + + + + + + org.alfresco.repo.content.transform.TransformerSelector + + @@ -339,14 +363,8 @@ - ${content.transformer.default.timeoutMs} - ${content.transformer.default.readLimitTimeMs} - ${content.transformer.default.maxSourceSizeKBytes} - ${content.transformer.default.readLimitKBytes} - ${content.transformer.default.pageLimit} - ${content.transformer.default.maxPages} - - + + @@ -373,35 +391,6 @@ - - - - application/vnd.apple.keynote - image/jpeg - - - application/vnd.apple.pages - image/jpeg - - - application/vnd.apple.numbers - image/jpeg - - - - application/vnd.apple.keynote - application/pdf - - - application/vnd.apple.pages - application/pdf - - - application/vnd.apple.numbers - application/pdf - - - - - - - application/pdf - text/plain - - - - - - - - application/pdf - image/png - - - - application/pdf - application/eps - - - application/pdf - image/jp2 - - - application/pdf - image/vnd.adobe.photoshop - - - application/pdf - image/vnd.adobe.premiere - - - application/pdf - image/cgm - - - application/pdf - image/gif - - - application/pdf - image/ief - - - application/pdf - image/bmp - - - application/pdf - image/jpeg - - - application/pdf - image/x-portable-bitmap - - - application/pdf - image/x-portable-graymap - - - application/pdf - image/x-portable-anymap - - - application/pdf - image/x-portable-pixmap - - - application/pdf - image/x-cmu-raster - - - application/pdf - image/tiff - - - application/pdf - image/x-xbitmap - - - application/pdf - image/x-xpixmap - - - application/pdf - image/x-xwindowdump - - - application/pdf - image/x-dwg - - - application/pdf - image/x-dwt - - - - - - - application/pdf - image/jpeg - - - application/pdf - image/gif - - - @@ -562,111 +438,6 @@ - - - - - application/illustrator - image/png - - - - application/illustrator - application/eps - - - application/illustrator - image/jp2 - - - application/illustrator - image/vnd.adobe.photoshop - - - application/illustrator - image/vnd.adobe.premiere - - - application/illustrator - image/cgm - - - application/illustrator - image/gif - - - application/illustrator - image/ief - - - application/illustrator - image/bmp - - - application/illustrator - image/jpeg - - - application/illustrator - image/x-portable-bitmap - - - application/illustrator - image/x-portable-graymap - - - application/illustrator - image/x-portable-anymap - - - application/illustrator - image/x-portable-pixmap - - - application/illustrator - image/x-cmu-raster - - - application/illustrator - image/tiff - - - application/illustrator - image/x-xbitmap - - - application/illustrator - image/x-xpixmap - - - application/illustrator - image/x-xwindowdump - - - application/illustrator - image/x-dwg - - - application/illustrator - image/x-dwt - - - - - - - application/illustrator - image/jpeg - - - application/illustrator - image/gif - - - @@ -678,22 +449,6 @@ - - - - application/vnd.apple.keynote - image/png - - - application/vnd.apple.numbers - image/png - - - application/vnd.apple.pages - image/png - - - @@ -739,27 +494,11 @@ application/pdf - - - - - - text/csv - application/pdf - - - text/xml - application/pdf - - - - ${content.transformer.PdfBox.TextToPdf.maxSourceSizeKBytes} application/pdf - - - - - text/csv - - - - text/xml - - - - - - - - application/msword - text/plain - - - - - - - text/html - text/plain - - - - - - - - - - text/html - application/pdf - - - - - - - - - - - - - * txt maxSourceSizeKBytes 0 ; - - txt pdf maxSourceSizeKBytes ${content.transformer.OpenOffice.mimeTypeLimits.txt.pdf.maxSourceSizeKBytes} ; - doc pdf maxSourceSizeKBytes ${content.transformer.OpenOffice.mimeTypeLimits.doc.pdf.maxSourceSizeKBytes} ; - docx pdf maxSourceSizeKBytes ${content.transformer.OpenOffice.mimeTypeLimits.docx.pdf.maxSourceSizeKBytes} ; - docm pdf maxSourceSizeKBytes ${content.transformer.OpenOffice.mimeTypeLimits.docm.pdf.maxSourceSizeKBytes} ; - dotx pdf maxSourceSizeKBytes ${content.transformer.OpenOffice.mimeTypeLimits.dotx.pdf.maxSourceSizeKBytes} ; - dotm pdf maxSourceSizeKBytes ${content.transformer.OpenOffice.mimeTypeLimits.dotm.pdf.maxSourceSizeKBytes} ; - ppt pdf maxSourceSizeKBytes ${content.transformer.OpenOffice.mimeTypeLimits.ppt.pdf.maxSourceSizeKBytes} ; - pptx pdf maxSourceSizeKBytes ${content.transformer.OpenOffice.mimeTypeLimits.pptx.pdf.maxSourceSizeKBytes} ; - pptm pdf maxSourceSizeKBytes ${content.transformer.OpenOffice.mimeTypeLimits.pptm.pdf.maxSourceSizeKBytes} ; - ppsx pdf maxSourceSizeKBytes ${content.transformer.OpenOffice.mimeTypeLimits.ppsx.pdf.maxSourceSizeKBytes} ; - ppsm pdf maxSourceSizeKBytes ${content.transformer.OpenOffice.mimeTypeLimits.ppsm.pdf.maxSourceSizeKBytes} ; - potx pdf maxSourceSizeKBytes ${content.transformer.OpenOffice.mimeTypeLimits.potx.pdf.maxSourceSizeKBytes} ; - potm pdf maxSourceSizeKBytes ${content.transformer.OpenOffice.mimeTypeLimits.potm.pdf.maxSourceSizeKBytes} ; - ppam pdf maxSourceSizeKBytes ${content.transformer.OpenOffice.mimeTypeLimits.ppam.pdf.maxSourceSizeKBytes} ; - sldx pdf maxSourceSizeKBytes ${content.transformer.OpenOffice.mimeTypeLimits.sldx.pdf.maxSourceSizeKBytes} ; - sldm pdf maxSourceSizeKBytes ${content.transformer.OpenOffice.mimeTypeLimits.sldm.pdf.maxSourceSizeKBytes} ; - vsd pdf maxSourceSizeKBytes ${content.transformer.OpenOffice.mimeTypeLimits.vsd.pdf.maxSourceSizeKBytes} ; - xls pdf maxSourceSizeKBytes ${content.transformer.OpenOffice.mimeTypeLimits.xls.pdf.maxSourceSizeKBytes} ; - xlsx pdf maxSourceSizeKBytes ${content.transformer.OpenOffice.mimeTypeLimits.xlsx.pdf.maxSourceSizeKBytes} ; - xltx pdf maxSourceSizeKBytes ${content.transformer.OpenOffice.mimeTypeLimits.xltx.pdf.maxSourceSizeKBytes} ; - xlsm pdf maxSourceSizeKBytes ${content.transformer.OpenOffice.mimeTypeLimits.xlsm.pdf.maxSourceSizeKBytes} ; - xltm pdf maxSourceSizeKBytes ${content.transformer.OpenOffice.mimeTypeLimits.xltm.pdf.maxSourceSizeKBytes} ; - xlam pdf maxSourceSizeKBytes ${content.transformer.OpenOffice.mimeTypeLimits.xlam.pdf.maxSourceSizeKBytes} ; - xlsb pdf maxSourceSizeKBytes ${content.transformer.OpenOffice.mimeTypeLimits.xlsb.pdf.maxSourceSizeKBytes} ; - - * docx maxSourceSizeKBytes 0 ; - * docm maxSourceSizeKBytes 0 ; - * dotx maxSourceSizeKBytes 0 ; - * dotm maxSourceSizeKBytes 0 ; - * pptx maxSourceSizeKBytes 0 ; - * pptm maxSourceSizeKBytes 0 ; - * ppsx maxSourceSizeKBytes 0 ; - * ppsm maxSourceSizeKBytes 0 ; - * potx maxSourceSizeKBytes 0 ; - * potm maxSourceSizeKBytes 0 ; - * ppam maxSourceSizeKBytes 0 ; - * sldx maxSourceSizeKBytes 0 ; - * sldm maxSourceSizeKBytes 0 ; - * xlsx maxSourceSizeKBytes 0 ; - * xltx maxSourceSizeKBytes 0 ; - * xlsm maxSourceSizeKBytes 0 ; - * xltm maxSourceSizeKBytes 0 ; - * xlam maxSourceSizeKBytes 0 ; - * xlsb maxSourceSizeKBytes 0 - - - - - application/pdf - - - - - - - - - - - - txt txt maxSourceSizeKBytes 0 ; - doc txt maxSourceSizeKBytes 0 ; - docx txt maxSourceSizeKBytes 0 ; - docm txt maxSourceSizeKBytes 0 ; - dotx txt maxSourceSizeKBytes 0 ; - dotm txt maxSourceSizeKBytes 0 ; - ppt txt maxSourceSizeKBytes 0 ; - pptx txt maxSourceSizeKBytes 0 ; - pptm txt maxSourceSizeKBytes 0 ; - ppsx txt maxSourceSizeKBytes 0 ; - ppsm txt maxSourceSizeKBytes 0 ; - potx txt maxSourceSizeKBytes 0 ; - potm txt maxSourceSizeKBytes ${content.transformer.OpenOffice.PdfBox.mimeTypeLimits.potm.txt.maxSourceSizeKBytes} ; - ppam txt maxSourceSizeKBytes 0 ; - sldx txt maxSourceSizeKBytes 0 ; - sldm txt maxSourceSizeKBytes 0 ; - xls txt maxSourceSizeKBytes 0 ; - xlsx txt maxSourceSizeKBytes 0 ; - xltx txt maxSourceSizeKBytes 0 ; - xlsm txt maxSourceSizeKBytes 0 ; - xltm txt maxSourceSizeKBytes 0 ; - xlam txt maxSourceSizeKBytes 0 ; - xlsb txt maxSourceSizeKBytes ${content.transformer.OpenOffice.PdfBox.mimeTypeLimits.xlsb.txt.maxSourceSizeKBytes} - - - - - - - - - application/zip - text/plain - - - diff --git a/config/alfresco/repository.properties b/config/alfresco/repository.properties index fd06463485..8ab8d8922e 100644 --- a/config/alfresco/repository.properties +++ b/config/alfresco/repository.properties @@ -606,85 +606,6 @@ system.thumbnail.quietPeriodRetriesEnabled=true # Content Transformers content.transformer.failover=true -# Base setting for all transformers (2 min timeout) -content.transformer.default.timeoutMs=120000 -content.transformer.default.readLimitTimeMs=-1 -content.transformer.default.maxSourceSizeKBytes=-1 -content.transformer.default.readLimitKBytes=-1 -content.transformer.default.pageLimit=-1 -content.transformer.default.maxPages=-1 - -# text -> pdf using PdfBox (text/csv, text/xml) 10M takes about 12 seconds -content.transformer.PdfBox.TextToPdf.maxSourceSizeKBytes=10240 - -# pdf -> swf using Pdf2swf 2M takes about 60 seconds. -content.transformer.Pdf2swf.maxSourceSizeKBytes=5120 - -# txt -> pdf -> swf 5M (pdf is about the same size as the txt) -# Need this limit as transformer.PdfBox txt -> pdf is allowed up to 10M -content.transformer.complex.Text.Pdf2swf.maxSourceSizeKBytes=5120 - -# Transforms to PDF -# ================= -content.transformer.OpenOffice.mimeTypeLimits.txt.pdf.maxSourceSizeKBytes=5120 -content.transformer.OpenOffice.mimeTypeLimits.doc.pdf.maxSourceSizeKBytes=10240 -content.transformer.OpenOffice.mimeTypeLimits.docx.pdf.maxSourceSizeKBytes=768 -content.transformer.OpenOffice.mimeTypeLimits.docm.pdf.maxSourceSizeKBytes=768 -content.transformer.OpenOffice.mimeTypeLimits.dotx.pdf.maxSourceSizeKBytes=768 -content.transformer.OpenOffice.mimeTypeLimits.dotm.pdf.maxSourceSizeKBytes=768 -content.transformer.OpenOffice.mimeTypeLimits.ppt.pdf.maxSourceSizeKBytes=6144 -content.transformer.OpenOffice.mimeTypeLimits.pptx.pdf.maxSourceSizeKBytes=4096 -content.transformer.OpenOffice.mimeTypeLimits.pptm.pdf.maxSourceSizeKBytes=4096 -content.transformer.OpenOffice.mimeTypeLimits.ppsx.pdf.maxSourceSizeKBytes=4096 -content.transformer.OpenOffice.mimeTypeLimits.ppsm.pdf.maxSourceSizeKBytes=4096 -content.transformer.OpenOffice.mimeTypeLimits.potx.pdf.maxSourceSizeKBytes=4096 -content.transformer.OpenOffice.mimeTypeLimits.potm.pdf.maxSourceSizeKBytes=4096 -content.transformer.OpenOffice.mimeTypeLimits.ppam.pdf.maxSourceSizeKBytes=4096 -content.transformer.OpenOffice.mimeTypeLimits.sldx.pdf.maxSourceSizeKBytes=4096 -content.transformer.OpenOffice.mimeTypeLimits.sldm.pdf.maxSourceSizeKBytes=4096 -content.transformer.OpenOffice.mimeTypeLimits.vsd.pdf.maxSourceSizeKBytes=4096 -content.transformer.OpenOffice.mimeTypeLimits.xls.pdf.maxSourceSizeKBytes=10240 -content.transformer.OpenOffice.mimeTypeLimits.xlsx.pdf.maxSourceSizeKBytes=1536 -content.transformer.OpenOffice.mimeTypeLimits.xltx.pdf.maxSourceSizeKBytes=1536 -content.transformer.OpenOffice.mimeTypeLimits.xlsm.pdf.maxSourceSizeKBytes=1536 -content.transformer.OpenOffice.mimeTypeLimits.xltm.pdf.maxSourceSizeKBytes=1536 -content.transformer.OpenOffice.mimeTypeLimits.xlam.pdf.maxSourceSizeKBytes=1536 -content.transformer.OpenOffice.mimeTypeLimits.xlsb.pdf.maxSourceSizeKBytes=1536 - -# Transforms to SWF -# ================= -content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.txt.swf.maxSourceSizeKBytes=5120 -content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.doc.swf.maxSourceSizeKBytes=1536 -content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.docx.swf.maxSourceSizeKBytes=256 -content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.docm.swf.maxSourceSizeKBytes=256 -content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.dotx.swf.maxSourceSizeKBytes=256 -content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.dotm.swf.maxSourceSizeKBytes=256 -content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.ppt.swf.maxSourceSizeKBytes=6144 -content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.pptx.swf.maxSourceSizeKBytes=4096 -content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.pptm.swf.maxSourceSizeKBytes=4096 -content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.ppsx.swf.maxSourceSizeKBytes=4096 -content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.ppsm.swf.maxSourceSizeKBytes=4096 -content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.potx.swf.maxSourceSizeKBytes=4096 -content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.potm.swf.maxSourceSizeKBytes=4096 -content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.ppam.swf.maxSourceSizeKBytes=4096 -content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.sldx.swf.maxSourceSizeKBytes=4096 -content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.sldm.swf.maxSourceSizeKBytes=4096 -content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.vsd.swf.maxSourceSizeKBytes=4096 -content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.xls.swf.maxSourceSizeKBytes=1024 -content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.xlsx.swf.maxSourceSizeKBytes=1024 -content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.xltx.swf.maxSourceSizeKBytes=1024 -content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.xlsm.swf.maxSourceSizeKBytes=1024 -content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.xltm.swf.maxSourceSizeKBytes=1024 -content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.xlam.swf.maxSourceSizeKBytes=1024 -content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.xlsb.swf.maxSourceSizeKBytes=1024 - - -# OpenOffice transforms to TXT (generally there are better options such as Tika) -# ============================= -content.transformer.OpenOffice.PdfBox.mimeTypeLimits.xlsb.txt.maxSourceSizeKBytes=1024 -content.transformer.OpenOffice.PdfBox.mimeTypeLimits.potm.txt.maxSourceSizeKBytes=1024 - - # Property to enable upgrade from 2.1-A V2.1-A.fixes.to.schema=0 #V2.1-A.fixes.to.schema=82 diff --git a/config/alfresco/subsystems/Transformers/default/transformers-context.xml b/config/alfresco/subsystems/Transformers/default/transformers-context.xml new file mode 100644 index 0000000000..2cd109474e --- /dev/null +++ b/config/alfresco/subsystems/Transformers/default/transformers-context.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/config/alfresco/subsystems/Transformers/default/transformers.properties b/config/alfresco/subsystems/Transformers/default/transformers.properties new file mode 100644 index 0000000000..550934c5af --- /dev/null +++ b/config/alfresco/subsystems/Transformers/default/transformers.properties @@ -0,0 +1,305 @@ +# Base setting for all transformers +# ================================= +content.transformer.default.priority=10 +content.transformer.default.thresholdCount=3 +content.transformer.default.time=0 +content.transformer.default.count=100000 +content.transformer.default.errorTime=120000 +content.transformer.default.timeoutMs=120000 +content.transformer.default.readLimitTimeMs=-1 +content.transformer.default.maxSourceSizeKBytes=-1 +content.transformer.default.readLimitKBytes=-1 +content.transformer.default.pageLimit=-1 +content.transformer.default.maxPages=-1 + + +# Transformer specific settings +# ============================= +content.transformer.ImageMagick.mimetypes.png.png.priority=5 +content.transformer.ImageMagick.mimetypes.pdf.png.priority=5 +content.transformer.ImageMagick.mimetypes.ai.png.priority=5 + +content.transformer.iWorksQuicklooks.mimetypes.key.jpg.priority=5 +content.transformer.iWorksQuicklooks.mimetypes.pages.jpg.priority=5 +content.transformer.iWorksQuicklooks.mimetypes.numbers.jpg.priority=5 +content.transformer.iWorksQuicklooks.mimetypes.key.pdf.priority=5 +content.transformer.iWorksQuicklooks.mimetypes.pages.pdf.priority=5 +content.transformer.iWorksQuicklooks.mimetypes.numbers.pdf.priority=5 + +content.transformer.PdfBox.mimetypes.pdf.txt.priority=5 + +content.transformer.complex.PDF.Image.mimetypes.pdf.png.supported=true +content.transformer.complex.PDF.Image.mimetypes.pdf.eps.supported=true +content.transformer.complex.PDF.Image.mimetypes.pdf.jp2.supported=true +content.transformer.complex.PDF.Image.mimetypes.pdf.psd.supported=true +content.transformer.complex.PDF.Image.mimetypes.pdf.ppj.supported=true +content.transformer.complex.PDF.Image.mimetypes.pdf.cgm.supported=true +content.transformer.complex.PDF.Image.mimetypes.pdf.gif.supported=true +content.transformer.complex.PDF.Image.mimetypes.pdf.ief.supported=true +content.transformer.complex.PDF.Image.mimetypes.pdf.bmp.supported=true +content.transformer.complex.PDF.Image.mimetypes.pdf.jpg.supported=true +content.transformer.complex.PDF.Image.mimetypes.pdf.pbm.supported=true +content.transformer.complex.PDF.Image.mimetypes.pdf.pgm.supported=true +content.transformer.complex.PDF.Image.mimetypes.pdf.pnm.supported=true +content.transformer.complex.PDF.Image.mimetypes.pdf.ppm.supported=true +content.transformer.complex.PDF.Image.mimetypes.pdf.ras.supported=true +content.transformer.complex.PDF.Image.mimetypes.pdf.tiff.supported=true +content.transformer.complex.PDF.Image.mimetypes.pdf.xbm.supported=true +content.transformer.complex.PDF.Image.mimetypes.pdf.xpm.supported=true +content.transformer.complex.PDF.Image.mimetypes.pdf.xwd.supported=true +content.transformer.complex.PDF.Image.mimetypes.pdf.bin.supported=true +content.transformer.complex.PDF.Image.mimetypes.pdf.dwt.supported=true +content.transformer.complex.PDF.Image.mimetypes.pdf.jpg.priority=5 +content.transformer.complex.PDF.Image.mimetypes.pdf.gif.priority=5 + +content.transformer.complex.AdobeIllustrator.Image.mimetypes.ai.png.supported=true +content.transformer.complex.AdobeIllustrator.Image.mimetypes.ai.eps.supported=true +content.transformer.complex.AdobeIllustrator.Image.mimetypes.ai.jp2.supported=true +content.transformer.complex.AdobeIllustrator.Image.mimetypes.ai.psd.supported=true +content.transformer.complex.AdobeIllustrator.Image.mimetypes.ai.ppj.supported=true +content.transformer.complex.AdobeIllustrator.Image.mimetypes.ai.cgm.supported=true +content.transformer.complex.AdobeIllustrator.Image.mimetypes.ai.gif.supported=true +content.transformer.complex.AdobeIllustrator.Image.mimetypes.ai.ief.supported=true +content.transformer.complex.AdobeIllustrator.Image.mimetypes.ai.bmp.supported=true +content.transformer.complex.AdobeIllustrator.Image.mimetypes.ai.jpg.supported=true +content.transformer.complex.AdobeIllustrator.Image.mimetypes.ai.pbm.supported=true +content.transformer.complex.AdobeIllustrator.Image.mimetypes.ai.pgm.supported=true +content.transformer.complex.AdobeIllustrator.Image.mimetypes.ai.pnm.supported=true +content.transformer.complex.AdobeIllustrator.Image.mimetypes.ai.ppm.supported=true +content.transformer.complex.AdobeIllustrator.Image.mimetypes.ai.ras.supported=true +content.transformer.complex.AdobeIllustrator.Image.mimetypes.ai.tiff.supported=true +content.transformer.complex.AdobeIllustrator.Image.mimetypes.ai.xbm.supported=true +content.transformer.complex.AdobeIllustrator.Image.mimetypes.ai.xpm.supported=true +content.transformer.complex.AdobeIllustrator.Image.mimetypes.ai.xwd.supported=true +content.transformer.complex.AdobeIllustrator.Image.mimetypes.ai.bin.supported=true +content.transformer.complex.AdobeIllustrator.Image.mimetypes.ai.dwt.supported=true +content.transformer.complex.AdobeIllustrator.Image.mimetypes.ai.jpg.priority=5 +content.transformer.complex.AdobeIllustrator.Image.mimetypes.ai.gif.priority=5 + +content.transformer.complex.iWorks.Image.mimetypes.key.png.priority=5 +content.transformer.complex.iWorks.Image.mimetypes.numbers.png.priority=5 +content.transformer.complex.iWorks.Image.mimetypes.pages.png.priority=5 + +content.transformer.OpenOffice.mimetypes.*.xlsm.supported=false +content.transformer.OpenOffice.mimetypes.*.pptm.supported=false +content.transformer.OpenOffice.mimetypes.*.sldm.supported=false +content.transformer.OpenOffice.mimetypes.*.xltx.supported=false +content.transformer.OpenOffice.mimetypes.*.docx.supported=false +content.transformer.OpenOffice.mimetypes.*.potx.supported=false +content.transformer.OpenOffice.mimetypes.*.xlsx.supported=false +content.transformer.OpenOffice.mimetypes.*.pptx.supported=false +content.transformer.OpenOffice.mimetypes.*.xlam.supported=false +content.transformer.OpenOffice.mimetypes.*.docm.supported=false +content.transformer.OpenOffice.mimetypes.*.xltm.supported=false +content.transformer.OpenOffice.mimetypes.*.dotx.supported=false +content.transformer.OpenOffice.mimetypes.*.xlsb.supported=false +content.transformer.OpenOffice.mimetypes.*.sldx.supported=false +content.transformer.OpenOffice.mimetypes.*.ppsm.supported=false +content.transformer.OpenOffice.mimetypes.*.txt.supported=false +content.transformer.OpenOffice.mimetypes.*.potm.supported=false +content.transformer.OpenOffice.mimetypes.*.ppam.supported=false +content.transformer.OpenOffice.mimetypes.*.dotm.supported=false +content.transformer.OpenOffice.mimetypes.*.ppsx.supported=false +content.transformer.OpenOffice.mimetypes.html.pdf.supported=false +content.transformer.OpenOffice.mimetypes.xlsm.pdf.maxSourceSizeKBytes=1536 +content.transformer.OpenOffice.mimetypes.pptm.pdf.maxSourceSizeKBytes=4096 +content.transformer.OpenOffice.mimetypes.xls.pdf.maxSourceSizeKBytes=10240 +content.transformer.OpenOffice.mimetypes.sldm.pdf.maxSourceSizeKBytes=4096 +content.transformer.OpenOffice.mimetypes.xltx.pdf.maxSourceSizeKBytes=1536 +content.transformer.OpenOffice.mimetypes.potx.pdf.maxSourceSizeKBytes=4096 +content.transformer.OpenOffice.mimetypes.docx.pdf.maxSourceSizeKBytes=768 +content.transformer.OpenOffice.mimetypes.xlsx.pdf.maxSourceSizeKBytes=1536 +content.transformer.OpenOffice.mimetypes.pptx.pdf.maxSourceSizeKBytes=4096 +content.transformer.OpenOffice.mimetypes.xlam.pdf.maxSourceSizeKBytes=1536 +content.transformer.OpenOffice.mimetypes.ppt.pdf.maxSourceSizeKBytes=6144 +content.transformer.OpenOffice.mimetypes.docm.pdf.maxSourceSizeKBytes=768 +content.transformer.OpenOffice.mimetypes.xltm.pdf.maxSourceSizeKBytes=1536 +content.transformer.OpenOffice.mimetypes.dotx.pdf.maxSourceSizeKBytes=768 +content.transformer.OpenOffice.mimetypes.xlsb.pdf.maxSourceSizeKBytes=1536 +content.transformer.OpenOffice.mimetypes.sldx.pdf.maxSourceSizeKBytes=4096 +content.transformer.OpenOffice.mimetypes.ppsm.pdf.maxSourceSizeKBytes=4096 +content.transformer.OpenOffice.mimetypes.potm.pdf.maxSourceSizeKBytes=4096 +content.transformer.OpenOffice.mimetypes.txt.pdf.maxSourceSizeKBytes=5120 +content.transformer.OpenOffice.mimetypes.ppam.pdf.maxSourceSizeKBytes=4096 +content.transformer.OpenOffice.mimetypes.dotm.pdf.maxSourceSizeKBytes=768 +content.transformer.OpenOffice.mimetypes.doc.pdf.maxSourceSizeKBytes=10240 +content.transformer.OpenOffice.mimetypes.vsd.pdf.maxSourceSizeKBytes=4096 +content.transformer.OpenOffice.mimetypes.ppsx.pdf.maxSourceSizeKBytes=4096 + +content.transformer.OpenOffice.Html2Pdf.mimetypes.html.pdf.supported=true +content.transformer.OpenOffice.Html2Pdf.mimetypes.html.pdf.priority=5 + +content.transformer.OpenOffice.2Pdf.mimetypes.*.pdf.supported=true + +content.transformer.PdfBox.TextToPdf.mimetypes.csv.pdf.supported=true +content.transformer.PdfBox.TextToPdf.mimetypes.xml.pdf.supported=true +content.transformer.PdfBox.TextToPdf.maxSourceSizeKBytes=10240 + +content.transformer.complex.Text.Image.mimetypes.csv.*.supported=true +content.transformer.complex.Text.Image.mimetypes.xml.*.supported=true +content.transformer.complex.Text.Image.mimetypes.txt.*.supported=true + +content.transformer.TextMining.mimetypes.doc.txt.priority=5 + +content.transformer.HtmlParser.mimetypes.html.txt.priority=5 + +content.transformer.complex.OpenOffice.PdfBox.mimetypes.xlsm.txt.supported=false +content.transformer.complex.OpenOffice.PdfBox.mimetypes.pptm.txt.supported=false +content.transformer.complex.OpenOffice.PdfBox.mimetypes.xls.txt.supported=false +content.transformer.complex.OpenOffice.PdfBox.mimetypes.sldm.txt.supported=false +content.transformer.complex.OpenOffice.PdfBox.mimetypes.xltx.txt.supported=false +content.transformer.complex.OpenOffice.PdfBox.mimetypes.docx.txt.supported=false +content.transformer.complex.OpenOffice.PdfBox.mimetypes.potx.txt.supported=false +content.transformer.complex.OpenOffice.PdfBox.mimetypes.xlsx.txt.supported=false +content.transformer.complex.OpenOffice.PdfBox.mimetypes.pptx.txt.supported=false +content.transformer.complex.OpenOffice.PdfBox.mimetypes.xlam.txt.supported=false +content.transformer.complex.OpenOffice.PdfBox.mimetypes.ppt.txt.supported=false +content.transformer.complex.OpenOffice.PdfBox.mimetypes.docm.txt.supported=false +content.transformer.complex.OpenOffice.PdfBox.mimetypes.xltm.txt.supported=false +content.transformer.complex.OpenOffice.PdfBox.mimetypes.dotx.txt.supported=false +content.transformer.complex.OpenOffice.PdfBox.mimetypes.sldx.txt.supported=false +content.transformer.complex.OpenOffice.PdfBox.mimetypes.ppsm.txt.supported=false +content.transformer.complex.OpenOffice.PdfBox.mimetypes.txt.txt.supported=false +content.transformer.complex.OpenOffice.PdfBox.mimetypes.ppam.txt.supported=false +content.transformer.complex.OpenOffice.PdfBox.mimetypes.dotm.txt.supported=false +content.transformer.complex.OpenOffice.PdfBox.mimetypes.doc.txt.supported=false +content.transformer.complex.OpenOffice.PdfBox.mimetypes.ppsx.txt.supported=false +content.transformer.complex.OpenOffice.PdfBox.mimetypes.xlsb.txt.maxSourceSizeKBytes=1024 +content.transformer.complex.OpenOffice.PdfBox.mimetypes.potm.txt.maxSourceSizeKBytes=1024 + +content.transformer.Archive.mimetypes.zip.txt.priority=5 + +content.transformer.Pdf2swf.maxSourceSizeKBytes=5120 +content.transformer.Pdf2swf.mimetypes.pdf.swf.supported=true +content.transformer.Pdf2swf.mimetypes.ai.swf.supported=true + +content.transformer.complex.OpenOffice.Pdf2swf.mimetypes.xlsm.swf.maxSourceSizeKBytes=1024 +content.transformer.complex.OpenOffice.Pdf2swf.mimetypes.pptm.swf.maxSourceSizeKBytes=4096 +content.transformer.complex.OpenOffice.Pdf2swf.mimetypes.xls.swf.maxSourceSizeKBytes=1024 +content.transformer.complex.OpenOffice.Pdf2swf.mimetypes.sldm.swf.maxSourceSizeKBytes=4096 +content.transformer.complex.OpenOffice.Pdf2swf.mimetypes.xltx.swf.maxSourceSizeKBytes=1024 +content.transformer.complex.OpenOffice.Pdf2swf.mimetypes.docx.swf.maxSourceSizeKBytes=256 +content.transformer.complex.OpenOffice.Pdf2swf.mimetypes.potx.swf.maxSourceSizeKBytes=4096 +content.transformer.complex.OpenOffice.Pdf2swf.mimetypes.xlsx.swf.maxSourceSizeKBytes=1024 +content.transformer.complex.OpenOffice.Pdf2swf.mimetypes.pptx.swf.maxSourceSizeKBytes=4096 +content.transformer.complex.OpenOffice.Pdf2swf.mimetypes.xlam.swf.maxSourceSizeKBytes=1024 +content.transformer.complex.OpenOffice.Pdf2swf.mimetypes.ppt.swf.maxSourceSizeKBytes=6144 +content.transformer.complex.OpenOffice.Pdf2swf.mimetypes.docm.swf.maxSourceSizeKBytes=256 +content.transformer.complex.OpenOffice.Pdf2swf.mimetypes.xltm.swf.maxSourceSizeKBytes=1024 +content.transformer.complex.OpenOffice.Pdf2swf.mimetypes.dotx.swf.maxSourceSizeKBytes=256 +content.transformer.complex.OpenOffice.Pdf2swf.mimetypes.xlsb.swf.maxSourceSizeKBytes=1024 +content.transformer.complex.OpenOffice.Pdf2swf.mimetypes.sldx.swf.maxSourceSizeKBytes=4096 +content.transformer.complex.OpenOffice.Pdf2swf.mimetypes.ppsm.swf.maxSourceSizeKBytes=4096 +content.transformer.complex.OpenOffice.Pdf2swf.mimetypes.potm.swf.maxSourceSizeKBytes=4096 +content.transformer.complex.OpenOffice.Pdf2swf.mimetypes.txt.swf.maxSourceSizeKBytes=5120 +content.transformer.complex.OpenOffice.Pdf2swf.mimetypes.ppam.swf.maxSourceSizeKBytes=4096 +content.transformer.complex.OpenOffice.Pdf2swf.mimetypes.dotm.swf.maxSourceSizeKBytes=256 +content.transformer.complex.OpenOffice.Pdf2swf.mimetypes.doc.swf.maxSourceSizeKBytes=1536 +content.transformer.complex.OpenOffice.Pdf2swf.mimetypes.vsd.swf.maxSourceSizeKBytes=4096 +content.transformer.complex.OpenOffice.Pdf2swf.mimetypes.ppsx.swf.maxSourceSizeKBytes=4096 + +content.transformer.complex.Text.Pdf2swf.mimetypes.csv.swf.supported=true +content.transformer.complex.Text.Pdf2swf.mimetypes.xml.swf.supported=true +content.transformer.complex.Text.Pdf2swf.maxSourceSizeKBytes=5120 + +content.transformer.complex.image.Pdf2swf.mimetypes.tiff.swf.supported=true + +content.transformer.JodConverter.mimetypes.*.xlsm.supported=false +content.transformer.JodConverter.mimetypes.*.pptm.supported=false +content.transformer.JodConverter.mimetypes.*.sldm.supported=false +content.transformer.JodConverter.mimetypes.*.xltx.supported=false +content.transformer.JodConverter.mimetypes.*.docx.supported=false +content.transformer.JodConverter.mimetypes.*.potx.supported=false +content.transformer.JodConverter.mimetypes.*.xlsx.supported=false +content.transformer.JodConverter.mimetypes.*.pptx.supported=false +content.transformer.JodConverter.mimetypes.*.xlam.supported=false +content.transformer.JodConverter.mimetypes.*.docm.supported=false +content.transformer.JodConverter.mimetypes.*.xltm.supported=false +content.transformer.JodConverter.mimetypes.*.dotx.supported=false +content.transformer.JodConverter.mimetypes.*.xlsb.supported=false +content.transformer.JodConverter.mimetypes.*.sldx.supported=false +content.transformer.JodConverter.mimetypes.*.ppsm.supported=false +content.transformer.JodConverter.mimetypes.*.txt.supported=false +content.transformer.JodConverter.mimetypes.*.potm.supported=false +content.transformer.JodConverter.mimetypes.*.ppam.supported=false +content.transformer.JodConverter.mimetypes.*.dotm.supported=false +content.transformer.JodConverter.mimetypes.*.ppsx.supported=false +content.transformer.JodConverter.mimetypes.html.pdf.supported=false +content.transformer.JodConverter.mimetypes.xlsm.pdf.maxSourceSizeKBytes=1536 +content.transformer.JodConverter.mimetypes.pptm.pdf.maxSourceSizeKBytes=4096 +content.transformer.JodConverter.mimetypes.xls.pdf.maxSourceSizeKBytes=10240 +content.transformer.JodConverter.mimetypes.sldm.pdf.maxSourceSizeKBytes=4096 +content.transformer.JodConverter.mimetypes.xltx.pdf.maxSourceSizeKBytes=1536 +content.transformer.JodConverter.mimetypes.potx.pdf.maxSourceSizeKBytes=4096 +content.transformer.JodConverter.mimetypes.docx.pdf.maxSourceSizeKBytes=768 +content.transformer.JodConverter.mimetypes.xlsx.pdf.maxSourceSizeKBytes=1536 +content.transformer.JodConverter.mimetypes.pptx.pdf.maxSourceSizeKBytes=4096 +content.transformer.JodConverter.mimetypes.xlam.pdf.maxSourceSizeKBytes=1536 +content.transformer.JodConverter.mimetypes.ppt.pdf.maxSourceSizeKBytes=6144 +content.transformer.JodConverter.mimetypes.docm.pdf.maxSourceSizeKBytes=768 +content.transformer.JodConverter.mimetypes.xltm.pdf.maxSourceSizeKBytes=1536 +content.transformer.JodConverter.mimetypes.dotx.pdf.maxSourceSizeKBytes=768 +content.transformer.JodConverter.mimetypes.xlsb.pdf.maxSourceSizeKBytes=1536 +content.transformer.JodConverter.mimetypes.sldx.pdf.maxSourceSizeKBytes=4096 +content.transformer.JodConverter.mimetypes.ppsm.pdf.maxSourceSizeKBytes=4096 +content.transformer.JodConverter.mimetypes.potm.pdf.maxSourceSizeKBytes=4096 +content.transformer.JodConverter.mimetypes.txt.pdf.maxSourceSizeKBytes=5120 +content.transformer.JodConverter.mimetypes.ppam.pdf.maxSourceSizeKBytes=4096 +content.transformer.JodConverter.mimetypes.dotm.pdf.maxSourceSizeKBytes=768 +content.transformer.JodConverter.mimetypes.doc.pdf.maxSourceSizeKBytes=10240 +content.transformer.JodConverter.mimetypes.vsd.pdf.maxSourceSizeKBytes=4096 +content.transformer.JodConverter.mimetypes.ppsx.pdf.maxSourceSizeKBytes=4096 + +content.transformer.JodConverter.Html2Pdf.mimetypes.html.pdf.supported=true +content.transformer.JodConverter.Html2Pdf.mimetypes.html.pdf.priority=5 + +content.transformer.JodConverter.2Pdf.mimetypes.*.pdf.supported=true + +content.transformer.complex.JodConverter.PdfBox.mimetypes.xlsm.txt.supported=false +content.transformer.complex.JodConverter.PdfBox.mimetypes.pptm.txt.supported=false +content.transformer.complex.JodConverter.PdfBox.mimetypes.xls.txt.supported=false +content.transformer.complex.JodConverter.PdfBox.mimetypes.sldm.txt.supported=false +content.transformer.complex.JodConverter.PdfBox.mimetypes.xltx.txt.supported=false +content.transformer.complex.JodConverter.PdfBox.mimetypes.docx.txt.supported=false +content.transformer.complex.JodConverter.PdfBox.mimetypes.potx.txt.supported=false +content.transformer.complex.JodConverter.PdfBox.mimetypes.xlsx.txt.supported=false +content.transformer.complex.JodConverter.PdfBox.mimetypes.pptx.txt.supported=false +content.transformer.complex.JodConverter.PdfBox.mimetypes.xlam.txt.supported=false +content.transformer.complex.JodConverter.PdfBox.mimetypes.ppt.txt.supported=false +content.transformer.complex.JodConverter.PdfBox.mimetypes.docm.txt.supported=false +content.transformer.complex.JodConverter.PdfBox.mimetypes.xltm.txt.supported=false +content.transformer.complex.JodConverter.PdfBox.mimetypes.dotx.txt.supported=false +content.transformer.complex.JodConverter.PdfBox.mimetypes.sldx.txt.supported=false +content.transformer.complex.JodConverter.PdfBox.mimetypes.ppsm.txt.supported=false +content.transformer.complex.JodConverter.PdfBox.mimetypes.txt.txt.supported=false +content.transformer.complex.JodConverter.PdfBox.mimetypes.ppam.txt.supported=false +content.transformer.complex.JodConverter.PdfBox.mimetypes.dotm.txt.supported=false +content.transformer.complex.JodConverter.PdfBox.mimetypes.doc.txt.supported=false +content.transformer.complex.JodConverter.PdfBox.mimetypes.ppsx.txt.supported=false +content.transformer.complex.JodConverter.PdfBox.mimetypes.xlsb.txt.maxSourceSizeKBytes=1024 +content.transformer.complex.JodConverter.PdfBox.mimetypes.potm.txt.maxSourceSizeKBytes=1024 + +content.transformer.complex.JodConverter.Pdf2swf.mimetypes.xlsm.swf.maxSourceSizeKBytes=1024 +content.transformer.complex.JodConverter.Pdf2swf.mimetypes.pptm.swf.maxSourceSizeKBytes=4096 +content.transformer.complex.JodConverter.Pdf2swf.mimetypes.xls.swf.maxSourceSizeKBytes=1024 +content.transformer.complex.JodConverter.Pdf2swf.mimetypes.sldm.swf.maxSourceSizeKBytes=4096 +content.transformer.complex.JodConverter.Pdf2swf.mimetypes.xltx.swf.maxSourceSizeKBytes=1024 +content.transformer.complex.JodConverter.Pdf2swf.mimetypes.docx.swf.maxSourceSizeKBytes=256 +content.transformer.complex.JodConverter.Pdf2swf.mimetypes.potx.swf.maxSourceSizeKBytes=4096 +content.transformer.complex.JodConverter.Pdf2swf.mimetypes.xlsx.swf.maxSourceSizeKBytes=1024 +content.transformer.complex.JodConverter.Pdf2swf.mimetypes.pptx.swf.maxSourceSizeKBytes=4096 +content.transformer.complex.JodConverter.Pdf2swf.mimetypes.xlam.swf.maxSourceSizeKBytes=1024 +content.transformer.complex.JodConverter.Pdf2swf.mimetypes.ppt.swf.maxSourceSizeKBytes=6144 +content.transformer.complex.JodConverter.Pdf2swf.mimetypes.docm.swf.maxSourceSizeKBytes=256 +content.transformer.complex.JodConverter.Pdf2swf.mimetypes.xltm.swf.maxSourceSizeKBytes=1024 +content.transformer.complex.JodConverter.Pdf2swf.mimetypes.dotx.swf.maxSourceSizeKBytes=256 +content.transformer.complex.JodConverter.Pdf2swf.mimetypes.xlsb.swf.maxSourceSizeKBytes=1024 +content.transformer.complex.JodConverter.Pdf2swf.mimetypes.sldx.swf.maxSourceSizeKBytes=4096 +content.transformer.complex.JodConverter.Pdf2swf.mimetypes.ppsm.swf.maxSourceSizeKBytes=4096 +content.transformer.complex.JodConverter.Pdf2swf.mimetypes.potm.swf.maxSourceSizeKBytes=4096 +content.transformer.complex.JodConverter.Pdf2swf.mimetypes.txt.swf.maxSourceSizeKBytes=5120 +content.transformer.complex.JodConverter.Pdf2swf.mimetypes.ppam.swf.maxSourceSizeKBytes=4096 +content.transformer.complex.JodConverter.Pdf2swf.mimetypes.dotm.swf.maxSourceSizeKBytes=256 +content.transformer.complex.JodConverter.Pdf2swf.mimetypes.doc.swf.maxSourceSizeKBytes=1536 +content.transformer.complex.JodConverter.Pdf2swf.mimetypes.vsd.swf.maxSourceSizeKBytes=4096 +content.transformer.complex.JodConverter.Pdf2swf.mimetypes.ppsx.swf.maxSourceSizeKBytes=4096 \ No newline at end of file diff --git a/config/alfresco/subsystems/thirdparty/default/swf-transform-context.xml b/config/alfresco/subsystems/thirdparty/default/swf-transform-context.xml index 9a1fa252f9..9a7f180c69 100644 --- a/config/alfresco/subsystems/thirdparty/default/swf-transform-context.xml +++ b/config/alfresco/subsystems/thirdparty/default/swf-transform-context.xml @@ -40,25 +40,8 @@ - - - - - application/pdf - - - application/x-shockwave-flash - - - - - application/illustrator - - - application/x-shockwave-flash - - - + + diff --git a/config/alfresco/swf-transform-context.xml b/config/alfresco/swf-transform-context.xml index 47d52cd681..9afb7e3f85 100644 --- a/config/alfresco/swf-transform-context.xml +++ b/config/alfresco/swf-transform-context.xml @@ -23,7 +23,6 @@ - ${content.transformer.Pdf2swf.maxSourceSizeKBytes} application/pdf - - - - - - - - - txt swf maxSourceSizeKBytes ${content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.txt.swf.maxSourceSizeKBytes} ; - doc swf maxSourceSizeKBytes ${content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.doc.swf.maxSourceSizeKBytes} ; - docx swf maxSourceSizeKBytes ${content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.docx.swf.maxSourceSizeKBytes} ; - docm swf maxSourceSizeKBytes ${content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.docm.swf.maxSourceSizeKBytes} ; - dotx swf maxSourceSizeKBytes ${content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.dotx.swf.maxSourceSizeKBytes} ; - dotm swf maxSourceSizeKBytes ${content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.dotm.swf.maxSourceSizeKBytes} ; - ppt swf maxSourceSizeKBytes ${content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.ppt.swf.maxSourceSizeKBytes} ; - pptx swf maxSourceSizeKBytes ${content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.pptx.swf.maxSourceSizeKBytes} ; - pptm swf maxSourceSizeKBytes ${content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.pptm.swf.maxSourceSizeKBytes} ; - ppsx swf maxSourceSizeKBytes ${content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.ppsx.swf.maxSourceSizeKBytes} ; - ppsm swf maxSourceSizeKBytes ${content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.ppsm.swf.maxSourceSizeKBytes} ; - potx swf maxSourceSizeKBytes ${content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.potx.swf.maxSourceSizeKBytes} ; - potm swf maxSourceSizeKBytes ${content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.potm.swf.maxSourceSizeKBytes} ; - ppam swf maxSourceSizeKBytes ${content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.ppam.swf.maxSourceSizeKBytes} ; - sldx swf maxSourceSizeKBytes ${content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.sldx.swf.maxSourceSizeKBytes} ; - sldm swf maxSourceSizeKBytes ${content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.sldm.swf.maxSourceSizeKBytes} ; - vsd swf maxSourceSizeKBytes ${content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.vsd.swf.maxSourceSizeKBytes} ; - xls swf maxSourceSizeKBytes ${content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.xls.swf.maxSourceSizeKBytes} ; - xlsx swf maxSourceSizeKBytes ${content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.xlsx.swf.maxSourceSizeKBytes} ; - xltx swf maxSourceSizeKBytes ${content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.xltx.swf.maxSourceSizeKBytes} ; - xlsm swf maxSourceSizeKBytes ${content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.xlsm.swf.maxSourceSizeKBytes} ; - xltm swf maxSourceSizeKBytes ${content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.xltm.swf.maxSourceSizeKBytes} ; - xlam swf maxSourceSizeKBytes ${content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.xlam.swf.maxSourceSizeKBytes} ; - xlsb swf maxSourceSizeKBytes ${content.transformer.OpenOffice.Pdf2swf.mimeTypeLimits.xlsb.swf.maxSourceSizeKBytes} - - - - - - - - @@ -114,23 +71,6 @@ application/pdf - - - - text/txt - application/x-shockwave-flash - - - text/csv - application/x-shockwave-flash - - - text/xml - application/x-shockwave-flash - - - - ${content.transformer.complex.Text.Pdf2swf.maxSourceSizeKBytes} @@ -164,7 +104,7 @@ - + @@ -190,14 +130,6 @@ application/pdf - - - - image/tiff - application/x-shockwave-flash - - - diff --git a/source/java/org/alfresco/repo/content/ContentServiceImpl.java b/source/java/org/alfresco/repo/content/ContentServiceImpl.java index 562bdb0ab7..bb2536a643 100644 --- a/source/java/org/alfresco/repo/content/ContentServiceImpl.java +++ b/source/java/org/alfresco/repo/content/ContentServiceImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2012 Alfresco Software Limited. + * Copyright (C) 2005-2013 Alfresco Software Limited. * * This file is part of Alfresco * @@ -803,7 +803,7 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa // check the file name if (MimetypeMap.MIMETYPE_TEXT_PLAIN.equals(sourceMimetype) && MimetypeMap.MIMETYPE_IMAGE_PNG.equals(targetMimetype) && - "debugTransformers.txt".equals(transformerDebug.getFileName(transformOptions, true, 0))) + transformerDebug.getFileName(transformOptions, true, 0).contains("debugTransformers.txt")) { Map> explicitTransforms = debugExplicitTransforms(); debugActiveTransformersByTransformer(explicitTransforms); diff --git a/source/java/org/alfresco/repo/content/transform/AbstractContentTransformer.java b/source/java/org/alfresco/repo/content/transform/AbstractContentTransformer.java index 96f65effae..7b57ab97be 100644 --- a/source/java/org/alfresco/repo/content/transform/AbstractContentTransformer.java +++ b/source/java/org/alfresco/repo/content/transform/AbstractContentTransformer.java @@ -30,6 +30,7 @@ import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.MimetypeService; import org.alfresco.service.cmr.repository.TransformationOptions; +import org.springframework.beans.factory.BeanNameAware; import org.springframework.extensions.surf.util.ParameterCheck; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -47,7 +48,7 @@ import org.apache.commons.logging.LogFactory; * @author Derek Hulley */ @Deprecated -public abstract class AbstractContentTransformer implements ContentTransformer +public abstract class AbstractContentTransformer implements ContentTransformer, BeanNameAware { private static final Log logger = LogFactory.getLog(AbstractContentTransformer.class); @@ -58,6 +59,9 @@ public abstract class AbstractContentTransformer implements ContentTransformer private double averageTime = 0.0; private long count = 0L; + /** The bean name. */ + private String beanName; + /** * All transformers start with an average transformation time of 0.0ms. */ @@ -408,6 +412,11 @@ public abstract class AbstractContentTransformer implements ContentTransformer return (long) averageTime; } + public long getTransformationTime(String sourceMimetype, String targetMimetype) + { + return (long) averageTime; + } + /** * Records and updates the average transformation time for this transformer. *

@@ -433,4 +442,29 @@ public abstract class AbstractContentTransformer implements ContentTransformer double diffTime = ((double) transformationTime) - averageTime; averageTime += diffTime / (double) count; } + + /** + * Sets the Spring bean name. + */ + @Override + public void setBeanName(String beanName) + { + this.beanName = beanName; + } + + /** + * Returns the Spring bean name. + */ + public String getBeanName() + { + return beanName; + } + + /** + * Returns transformer name. Uses the Spring bean name, but if null uses the class name. + */ + public String getName() + { + return (beanName == null) ? getClass().getSimpleName() : beanName; + } } diff --git a/source/java/org/alfresco/repo/content/transform/AbstractContentTransformer2.java b/source/java/org/alfresco/repo/content/transform/AbstractContentTransformer2.java index 9b8d69d387..de8ec07585 100644 --- a/source/java/org/alfresco/repo/content/transform/AbstractContentTransformer2.java +++ b/source/java/org/alfresco/repo/content/transform/AbstractContentTransformer2.java @@ -19,7 +19,6 @@ package org.alfresco.repo.content.transform; import java.util.Map; -import java.util.Properties; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.service.cmr.repository.ContentIOException; @@ -46,13 +45,20 @@ public abstract class AbstractContentTransformer2 extends AbstractContentTransfo private static final Log logger = LogFactory.getLog(AbstractContentTransformer2.class); private ContentTransformerRegistry registry; - private Properties properties; - private double averageTime; - private long count = 0L; - + + private ThreadLocal depth = new ThreadLocal() + { + @Override + protected Integer initialValue() + { + return 0; + } + }; + /** * All transformers start with an average transformation time of 0.0 ms, - * unless there is an Alfresco global property {@code .initialTime}. + * unless there is an Alfresco global property {@code .time}. + * May also be set for given combinations of source and target mimetypes. */ protected AbstractContentTransformer2() { @@ -68,70 +74,12 @@ public abstract class AbstractContentTransformer2 extends AbstractContentTransfo this.registry = registry; } - /** - * The Alfresco global properties. - */ - public void setProperties(Properties properties) - { - this.properties = properties; - } - - /** - * Sets the averageTime and count (if global properties were used to set the averageTime). - * Both default to 0. The property names use the transformer bean name with a ".time" - * or ".count" suffix. Spring bean configuration is not being used as we don't wish to - * break existing transformers that know nothing about these properties. - */ - private void setAverageTimeFromAlfrescoGlobalProperties() - { - String beanName = getBeanName(); - averageTime = Long.valueOf(getPositiveLongProperty(beanName+".time", 0L)); - if (averageTime > 0.0) - { - // This normally is a large number so that it does not change much if used. - count = Long.valueOf(getPositiveLongProperty(beanName+".count", 10000)); - } - } - - /** - * Returns a positive long value from an optional Alfresco global property. - * Invalid values are ignored but a log message is issued. - * @param name of the property - * @param defaultValue if the property does not exist or is negative - * @return the value - */ - private long getPositiveLongProperty(String name, long defaultValue) - { - long value = defaultValue; - if (properties != null) - { - String property = properties.getProperty(name); - if (property != null) - { - try - { - value = Long.valueOf(property); - if (value < 0) - { - value = defaultValue; - throw new NumberFormatException(); - } - } - catch (NumberFormatException e) - { - logger.warn("Alfresco global property "+name+" is must be a positive Java long value. Using "+defaultValue); - } - } - } - return value; - } - @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(this.getClass().getSimpleName()) - .append("[ average=").append((long)averageTime).append("ms") + .append("[ average=").append(transformerConfig.getStatistics(this, null, null).getAverageTime()).append("ms") .append("]"); return sb.toString(); } @@ -140,10 +88,12 @@ public abstract class AbstractContentTransformer2 extends AbstractContentTransfo * Registers this instance with the {@link #setRegistry(ContentTransformerRegistry) registry} * if it is present. * - * THIS IS A CUSTOME SPRING INIT METHOD + * THIS IS A CUSTOM SPRING INIT METHOD */ public void register() { + super.register(); + if (registry == null) { logger.warn("Property 'registry' has not been set. Ignoring auto-registration: \n" + @@ -151,8 +101,6 @@ public abstract class AbstractContentTransformer2 extends AbstractContentTransfo return; } - setAverageTimeFromAlfrescoGlobalProperties(); - // register this instance for the fallback case registry.addTransformer(this); } @@ -211,115 +159,127 @@ public abstract class AbstractContentTransformer2 extends AbstractContentTransfo public final void transform(ContentReader reader, ContentWriter writer, TransformationOptions options) throws ContentIOException { - // begin timing - long before = System.currentTimeMillis(); - - // check options map - if (options == null) - { - options = new TransformationOptions(); - } - try { - if (transformerDebug.isEnabled()) + depth.set(depth.get()+1); + + // begin timing + long before = System.currentTimeMillis(); + + String sourceMimetype = reader.getMimetype(); + String targetMimetype = writer.getMimetype(); + + // check options map + if (options == null) { - transformerDebug.pushTransform(this, reader.getContentUrl(), reader.getMimetype(), - writer.getMimetype(), reader.getSize(), options); + options = new TransformationOptions(); } - // Check the transformability - checkTransformable(reader, writer, options); - - // Pass on any limits to the reader - setReaderLimits(reader, writer, options); + try + { + if (transformerDebug.isEnabled()) + { + transformerDebug.pushTransform(this, reader.getContentUrl(), sourceMimetype, + targetMimetype, reader.getSize(), options); + } + + // Check the transformability + checkTransformable(reader, writer, options); + + // Pass on any limits to the reader + setReaderLimits(reader, writer, options); - // Transform - transformInternal(reader, writer, options); - } - catch (ContentServiceTransientException cste) - { - // A transient failure has occurred within the content transformer. - // This should not be interpreted as a failure and therefore we should not - // update the transformer's average time. + // Transform + transformInternal(reader, writer, options); + } + catch (ContentServiceTransientException cste) + { + // A transient failure has occurred within the content transformer. + // This should not be interpreted as a failure and therefore we should not + // update the transformer's average time. + if (logger.isDebugEnabled()) + { + logger.debug("Transformation has been transiently declined: \n" + + " reader: " + reader + "\n" + + " writer: " + writer + "\n" + + " options: " + options + "\n" + + " transformer: " + this); + } + // the finally block below will still perform tidyup. Otherwise we're done. + // We rethrow the exception + throw cste; + } + catch (Throwable e) + { + // Make sure that this transformation gets set back i.t.o. time taken. + // This will ensure that transformers that compete for the same transformation + // will be prejudiced against transformers that tend to fail + recordError(sourceMimetype, targetMimetype); + + // Ask Tika to detect the document, and report back on if + // the current mime type is plausible + String differentType = getMimetypeService().getMimetypeIfNotMatches(reader.getReader()); + + // Report the error + if(differentType == null) + { + transformerDebug.debug(" Failed", e); + throw new ContentIOException("Content conversion failed: \n" + + " reader: " + reader + "\n" + + " writer: " + writer + "\n" + + " options: " + options.toString(false) + "\n" + + " limits: " + getLimits(reader, writer, options), + e); + } + else + { + transformerDebug.debug(" Failed: Mime type was '"+differentType+"'", e); + throw new ContentIOException("Content conversion failed: \n" + + " reader: " + reader + "\n" + + " writer: " + writer + "\n" + + " options: " + options.toString(false) + "\n" + + " limits: " + getLimits(reader, writer, options) + "\n" + + " claimed mime type: " + reader.getMimetype() + "\n" + + " detected mime type: " + differentType, + e); + } + } + finally + { + transformerDebug.popTransform(); + + // check that the reader and writer are both closed + if (reader.isChannelOpen()) + { + logger.error("Content reader not closed by transformer: \n" + + " reader: " + reader + "\n" + + " transformer: " + this); + } + if (writer.isChannelOpen()) + { + logger.error("Content writer not closed by transformer: \n" + + " writer: " + writer + "\n" + + " transformer: " + this); + } + } + + // record time + long after = System.currentTimeMillis(); + recordTime(sourceMimetype, targetMimetype, after - before); + + // done if (logger.isDebugEnabled()) { - logger.debug("Transformation has been transiently declined: \n" + + logger.debug("Completed transformation: \n" + " reader: " + reader + "\n" + " writer: " + writer + "\n" + " options: " + options + "\n" + " transformer: " + this); } - // the finally block below will still perform tidyup. Otherwise we're done. - // We rethrow the exception - throw cste; - } - catch (Throwable e) - { - // Make sure that this transformation gets set back i.t.o. time taken. - // This will ensure that transformers that compete for the same transformation - // will be prejudiced against transformers that tend to fail - recordTime(60 * 1000); // 1 minute, i.e. rubbish - - // Ask Tika to detect the document, and report back on if - // the current mime type is plausible - String differentType = getMimetypeService().getMimetypeIfNotMatches(reader.getReader()); - - // Report the error - if(differentType == null) - { - transformerDebug.debug(" Failed", e); - throw new ContentIOException("Content conversion failed: \n" + - " reader: " + reader + "\n" + - " writer: " + writer + "\n" + - " options: " + options.toString(false) + "\n" + - " limits: " + getLimits(reader, writer, options), - e); - } - else - { - transformerDebug.debug(" Failed: Mime type was '"+differentType+"'", e); - throw new ContentIOException("Content conversion failed: \n" + - " reader: " + reader + "\n" + - " writer: " + writer + "\n" + - " options: " + options.toString(false) + "\n" + - " limits: " + getLimits(reader, writer, options) + "\n" + - " claimed mime type: " + reader.getMimetype() + "\n" + - " detected mime type: " + differentType, - e); - } } finally { - transformerDebug.popTransform(); - - // check that the reader and writer are both closed - if (reader.isChannelOpen()) - { - logger.error("Content reader not closed by transformer: \n" + - " reader: " + reader + "\n" + - " transformer: " + this); - } - if (writer.isChannelOpen()) - { - logger.error("Content writer not closed by transformer: \n" + - " writer: " + writer + "\n" + - " transformer: " + this); - } - } - - // record time - long after = System.currentTimeMillis(); - recordTime(after - before); - - // done - if (logger.isDebugEnabled()) - { - logger.debug("Completed transformation: \n" + - " reader: " + reader + "\n" + - " writer: " + writer + "\n" + - " options: " + options + "\n" + - " transformer: " + this); + depth.set(depth.get()+1); } } @@ -336,7 +296,23 @@ public abstract class AbstractContentTransformer2 extends AbstractContentTransfo */ public synchronized long getTransformationTime() { - return (long) averageTime; + return transformerConfig.getStatistics(this, null, null).getAverageTime(); + } + + /** + * @return Returns the calculated running average of the current transformations + */ + public synchronized long getTransformationTime(String sourceMimetype, String targetMimetype) + { + return transformerConfig.getStatistics(this, sourceMimetype, targetMimetype).getAverageTime(); + } + + /** + * @deprecated use method with mimetypes. + */ + protected final synchronized void recordTime(long transformationTime) + { + recordTime(TransformerConfig.ANY, TransformerConfig.ANY, transformationTime); } /** @@ -348,20 +324,33 @@ public abstract class AbstractContentTransformer2 extends AbstractContentTransfo * This method is thread-safe. The time spent in this method is negligible * so the impact will be minor. * + * @param sourceMimetype + * @param targetMimetype * @param transformationTime the time it took to perform the transformation. * The value may be 0. */ - protected final synchronized void recordTime(long transformationTime) + protected final synchronized void recordTime(String sourceMimetype, String targetMimetype, + long transformationTime) { - if (count == Long.MAX_VALUE) + transformerConfig.getStatistics(this, sourceMimetype, targetMimetype).recordTime(transformationTime); + if (depth.get() == 1) { - // we have reached the max count - reduce it by half - // the average fluctuation won't be extreme - count /= 2L; + transformerConfig.getStatistics(null, sourceMimetype, targetMimetype).recordTime(transformationTime); + } + } + + /** + * Records an error and updates the average time as if the transformation took a + * long time, so that it is less likely to be called again. + * @param sourceMimetype + * @param targetMimetype + */ + protected final synchronized void recordError(String sourceMimetype, String targetMimetype) + { + transformerConfig.getStatistics(this, sourceMimetype, targetMimetype).recordError(); + if (depth.get() == 1) + { + transformerConfig.getStatistics(null, sourceMimetype, targetMimetype).recordError(); } - // adjust the average - count++; - double diffTime = ((double) transformationTime) - averageTime; - averageTime += diffTime / (double) count; } } diff --git a/source/java/org/alfresco/repo/content/transform/AbstractContentTransformerLimits.java b/source/java/org/alfresco/repo/content/transform/AbstractContentTransformerLimits.java index e0fb105d35..3fdb505b4e 100644 --- a/source/java/org/alfresco/repo/content/transform/AbstractContentTransformerLimits.java +++ b/source/java/org/alfresco/repo/content/transform/AbstractContentTransformerLimits.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2012 Alfresco Software Limited. + * Copyright (C) 2005-2013 Alfresco Software Limited. * * This file is part of Alfresco * @@ -18,14 +18,22 @@ */ package org.alfresco.repo.content.transform; +import static org.alfresco.service.cmr.repository.TransformationOptionLimits.OPT_MAX_PAGES; +import static org.alfresco.service.cmr.repository.TransformationOptionLimits.OPT_MAX_SOURCE_SIZE_K_BYTES; +import static org.alfresco.service.cmr.repository.TransformationOptionLimits.OPT_PAGE_LIMIT; +import static org.alfresco.service.cmr.repository.TransformationOptionLimits.OPT_READ_LIMIT_K_BYTES; +import static org.alfresco.service.cmr.repository.TransformationOptionLimits.OPT_READ_LIMIT_TIME_MS; +import static org.alfresco.service.cmr.repository.TransformationOptionLimits.OPT_TIMEOUT_MS; + import java.util.Map; +import java.util.Map.Entry; import org.alfresco.repo.content.AbstractContentReader; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.repository.MimetypeService; import org.alfresco.service.cmr.repository.TransformationOptionLimits; import org.alfresco.service.cmr.repository.TransformationOptions; -import org.springframework.beans.factory.BeanNameAware; /** * Provides transformation limits for {@link org.alfresco.repo.content.transform.ContentTransformer} @@ -38,26 +46,14 @@ import org.springframework.beans.factory.BeanNameAware; * * @author Alan Davis */ -public abstract class AbstractContentTransformerLimits extends ContentTransformerHelper implements ContentTransformer, BeanNameAware +public abstract class AbstractContentTransformerLimits extends ContentTransformerHelper implements ContentTransformer { - /** Transformer wide Time, KBytes and page limits */ - private TransformationOptionLimits limits = new TransformationOptionLimits(); - - /** - * Time, KBytes and page limits by source and target mimetype combination. - * The first map's key is the source mimetype. The second map's key is the - * target mimetype and the value are the limits. */ - private Map> mimetypeLimits; - /** Indicates if 'page' limits are supported. */ private boolean pageLimitsSupported; /** For debug **/ protected TransformerDebug transformerDebug; - /** The bean name. Used in debug only. */ - private String beanName; - /** * Indicates if 'page' limits are supported. * @return false by default. @@ -172,21 +168,17 @@ public abstract class AbstractContentTransformerLimits extends ContentTransforme */ protected long getTimeoutMs() { - return limits.getTimeoutMs(); + return getLimits().getTimeoutMs(); } /** - * Sets a timeout (ms) on the InputStream after which an IOExecption is thrown - * to terminate very slow transformations or to terminate (kill) a subprocess. - * @param timeoutMs in milliseconds. If less than or equal to zero (the default) - * there is no timeout. - * If greater than zero the {@code readLimitTimeMs} must not be set. + * @deprecated transformation limits are now set with global properties rather than spring configuration. */ public void setTimeoutMs(long timeoutMs) { - limits.setTimeoutMs(timeoutMs); + deprecatedSetter(OPT_TIMEOUT_MS+'='+timeoutMs); } - + /** * Gets the limit in terms of the amount of data read (by time) to limit transformations where * only the start of the content is needed. After this limit is reached the InputStream reports @@ -195,19 +187,15 @@ public abstract class AbstractContentTransformerLimits extends ContentTransforme */ protected long getReadLimitTimeMs() { - return limits.getReadLimitTimeMs(); + return getLimits().getReadLimitTimeMs(); } /** - * Sets a limit in terms of the amount of data read (by time) to limit transformations where - * only the start of the content is needed. After this limit is reached the InputStream reports - * end of file. - * @param readLimitBytes if less than or equal to zero (the default) there is no limit. - * If greater than zero the {@code timeoutMs} must not be set. + * @deprecated transformation limits are now set with global properties rather than spring configuration. */ public void setReadLimitTimeMs(long readLimitTimeMs) { - limits.setReadLimitTimeMs(readLimitTimeMs); + deprecatedSetter(OPT_READ_LIMIT_TIME_MS+'='+readLimitTimeMs); } /** @@ -218,19 +206,15 @@ public abstract class AbstractContentTransformerLimits extends ContentTransforme */ protected long getMaxSourceSizeKBytes() { - return limits.getMaxSourceSizeKBytes(); + return getLimits().getMaxSourceSizeKBytes(); } /** - * Sets a maximum source content size, to skip transformations where - * the source is just too large to expect it to perform. If the source is larger - * the transformer indicates it is not available. - * @param maxSourceSizeKBytes if less than or equal to zero (the default) there is no limit. - * If greater than zero the {@code readLimitKBytes} must not be set. + * @deprecated transformation limits are now set with global properties rather than spring configuration. */ public void setMaxSourceSizeKBytes(long maxSourceSizeKBytes) { - limits.setMaxSourceSizeKBytes(maxSourceSizeKBytes); + deprecatedSetter(OPT_MAX_SOURCE_SIZE_K_BYTES+'='+maxSourceSizeKBytes); } /** @@ -241,19 +225,15 @@ public abstract class AbstractContentTransformerLimits extends ContentTransforme */ protected long getReadLimitKBytes() { - return limits.getReadLimitKBytes(); + return getLimits().getReadLimitKBytes(); } /** - * Sets a limit in terms of the about of data read to limit transformations where - * only the start of the content is needed. After this limit is reached the InputStream reports - * end of file. - * @param readLimitKBytes if less than or equal to zero (the default) there is no limit. - * If greater than zero the {@code maxSourceSizeKBytes} must not be set. + * @deprecated transformation limits are now set with global properties rather than spring configuration. */ public void setReadLimitKBytes(long readLimitKBytes) { - limits.setReadLimitKBytes(readLimitKBytes); + deprecatedSetter(OPT_READ_LIMIT_K_BYTES+'='+readLimitKBytes); } /** @@ -262,18 +242,15 @@ public abstract class AbstractContentTransformerLimits extends ContentTransforme */ protected int getMaxPages() { - return limits.getMaxPages(); + return getLimits().getMaxPages(); } /** - * Set the number of pages read from the source before an exception is thrown. - * - * @param maxPages the number of pages to be read from the source. If less than or equal to zero - * (the default) no limit is applied. + * @deprecated transformation limits are now set with global properties rather than spring configuration. */ public void setMaxPages(int maxPages) { - limits.setMaxPages(maxPages); + deprecatedSetter(OPT_MAX_PAGES+'='+maxPages); } /** @@ -282,18 +259,15 @@ public abstract class AbstractContentTransformerLimits extends ContentTransforme */ protected int getPageLimit() { - return limits.getPageLimit(); + return getLimits().getPageLimit(); } /** - * Set the number of pages read from the source before returning EOF. - * - * @param pageLimit the number of pages to be read from the source. If less - * than or equal to zero (the default) no limit is applied. + * @deprecated transformation limits are now set with global properties rather than spring configuration. */ public void setPageLimit(int pageLimit) { - limits.setPageLimit(pageLimit); + deprecatedSetter(OPT_PAGE_LIMIT+'='+pageLimit); } /** @@ -301,33 +275,57 @@ public abstract class AbstractContentTransformerLimits extends ContentTransforme */ protected TransformationOptionLimits getLimits() { - return limits; + return transformerConfig.getLimits(this, null, null); } - + /** - * Sets max and limit values for time, size and pages in a single operation. + * @deprecated transformation limits are now set with global properties rather than spring configuration. */ public void setLimits(TransformationOptionLimits limits) { - this.limits = limits; + deprecatedLimitsSetter("", limits); } /** - * Gets the max and limit values for time, size and pages per source and target mimetype - * combination. - */ - protected Map> getMimetypeLimits() - { - return mimetypeLimits; - } - - /** - * Sets the max and limit values for time, size and pages per source and target mimetype - * combination. + * @deprecated transformation limits are now set with global properties rather than spring configuration. */ public void setMimetypeLimits(Map> mimetypeLimits) { - this.mimetypeLimits = mimetypeLimits; + for (Entry> source: mimetypeLimits.entrySet()) + { + String sourceExt = getExtensionOrAny(source.getKey()); + for (Entry target: source.getValue().entrySet()) + { + String targetExt = getExtensionOrAny(target.getKey()); + TransformationOptionLimits limits = target.getValue(); + String mimetypeSuffix = TransformerConfig.MIMETYPES_SEPARATOR.substring(1)+sourceExt+'.'+targetExt; + + deprecatedLimitsSetter(mimetypeSuffix, limits); + } + } + } + + private void deprecatedLimitsSetter(String mimetypeSuffix, TransformationOptionLimits limits) + { + if (limits.supported()) + { + // Ignore limit pairs that are not specified + for (String limit: new String[] { + limits.getTimePair().toString(OPT_TIMEOUT_MS, OPT_READ_LIMIT_TIME_MS), + limits.getKBytesPair().toString(OPT_MAX_SOURCE_SIZE_K_BYTES, OPT_READ_LIMIT_K_BYTES), + limits.getPagesPair().toString(OPT_MAX_PAGES, OPT_PAGE_LIMIT) + }) + { + if (limit != null) + { + deprecatedSetter(mimetypeSuffix+'.'+limit); + } + } + } + else + { + deprecatedSetter(mimetypeSuffix+TransformerConfig.SUPPORTED+"=false"); + } } /** @@ -339,7 +337,7 @@ public abstract class AbstractContentTransformerLimits extends ContentTransforme TransformationOptions options) { return (reader == null || writer == null) - ? limits.combine(options.getLimits()) + ? getLimits().combine(options.getLimits()) : getLimits(reader.getMimetype(), writer.getMimetype(), options); } @@ -351,63 +349,8 @@ public abstract class AbstractContentTransformerLimits extends ContentTransforme protected TransformationOptionLimits getLimits(String sourceMimetype, String targetMimetype, TransformationOptions options) { - // Get the limits for the source and target mimetypes - TransformationOptionLimits mimetypeLimits = null; - if (this.mimetypeLimits != null) - { - boolean anySource = false; - Map targetLimits = - this.mimetypeLimits.get(sourceMimetype); - if (targetLimits == null) - { - targetLimits = this.mimetypeLimits.get("*"); - anySource = true; - } - if (targetLimits != null) - { - mimetypeLimits = targetLimits.get(targetMimetype); - if (mimetypeLimits == null) - { - mimetypeLimits = targetLimits.get("*"); - - // Allow for the case where have specific source and target mimetype limits - // and general source limits (avoid having to repeat the general values in - // each specific source definition) - if (mimetypeLimits == null && !anySource) - { - targetLimits = this.mimetypeLimits.get("*"); - if (targetLimits != null) - { - mimetypeLimits = targetLimits.get(targetMimetype); - if (mimetypeLimits == null) - { - mimetypeLimits = targetLimits.get("*"); - } - } - } - } - } - } - - TransformationOptionLimits combined = (mimetypeLimits == null) ? limits : limits.combine(mimetypeLimits); - return (options == null) ? combined : combined.combine(options.getLimits()); - } - - /** - * Sets the Spring bean name - only for use in debug. - */ - @Override - public void setBeanName(String beanName) - { - this.beanName = beanName; - } - - /** - * Returns the Spring bean name - only for use in debug. - */ - public String getBeanName() - { - return beanName; + TransformationOptionLimits limits = transformerConfig.getLimits(this, sourceMimetype, targetMimetype); + return (options == null) ? limits : limits.combine(options.getLimits()); } /** diff --git a/source/java/org/alfresco/repo/content/transform/AbstractContentTransformerLimitsTest.java b/source/java/org/alfresco/repo/content/transform/AbstractContentTransformerLimitsTest.java index 1d5ce5d665..7a779f2e3d 100644 --- a/source/java/org/alfresco/repo/content/transform/AbstractContentTransformerLimitsTest.java +++ b/source/java/org/alfresco/repo/content/transform/AbstractContentTransformerLimitsTest.java @@ -28,6 +28,7 @@ import java.util.Map; import org.alfresco.repo.content.AbstractContentReader; import org.alfresco.repo.content.ContentMinimalContextTestSuite; import org.alfresco.repo.content.AbstractContentReaderLimitTest.DummyAbstractContentReader; +import org.alfresco.repo.content.MimetypeMap; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentWriter; @@ -43,9 +44,9 @@ import org.springframework.context.ApplicationContext; */ public class AbstractContentTransformerLimitsTest { - private static final String A = "a"; - private static final String B = "b"; - private static final String C = "c"; + private static final String A = MimetypeMap.MIMETYPE_XML; + private static final String B = MimetypeMap.MIMETYPE_HTML; + private static final String C = MimetypeMap.MIMETYPE_PDF; private AbstractContentTransformerLimits transformer; private TransformationOptionLimits limits; @@ -59,6 +60,7 @@ public class AbstractContentTransformerLimitsTest ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY); MimetypeService mimetypeService = serviceRegistry.getMimetypeService(); TransformerDebug transformerDebug = (TransformerDebug) ctx.getBean("transformerDebug"); + TransformerConfig transformerConfig = (TransformerConfig) ctx.getBean("transformerConfig"); transformer = new AbstractContentTransformer2() { @@ -77,6 +79,8 @@ public class AbstractContentTransformerLimitsTest }; transformer.setMimetypeService(mimetypeService); transformer.setTransformerDebug(transformerDebug); + transformer.setTransformerConfig(transformerConfig); + transformer.setBeanName("transformer.test"+System.currentTimeMillis()%100000); limits = new TransformationOptionLimits(); options = new TransformationOptions(); @@ -104,6 +108,7 @@ public class AbstractContentTransformerLimitsTest { long value = 1234; transformer.setTimeoutMs(value); + transformer.register(); long actual = transformer.getTimeoutMs(); assertEquals("Getter did not return set value", value, actual); } @@ -113,6 +118,7 @@ public class AbstractContentTransformerLimitsTest { long value = 1234; transformer.setReadLimitTimeMs(value); + transformer.register(); long actual = transformer.getReadLimitTimeMs(); assertEquals("Getter did not return set value", value, actual); } @@ -122,6 +128,7 @@ public class AbstractContentTransformerLimitsTest { long value = 1234; transformer.setMaxSourceSizeKBytes(value); + transformer.register(); long actual = transformer.getMaxSourceSizeKBytes(); assertEquals("Getter did not return set value", value, actual); } @@ -131,6 +138,7 @@ public class AbstractContentTransformerLimitsTest { long value = 1234; transformer.setReadLimitKBytes(value); + transformer.register(); long actual = transformer.getReadLimitKBytes(); assertEquals("Getter did not return set value", value, actual); } @@ -140,6 +148,7 @@ public class AbstractContentTransformerLimitsTest { int value = 1234; transformer.setMaxPages(value); + transformer.register(); int actual = transformer.getMaxPages(); assertEquals("Getter did not return set value", value, actual); } @@ -149,6 +158,7 @@ public class AbstractContentTransformerLimitsTest { int value = 1234; transformer.setPageLimit(value); + transformer.register(); int actual = transformer.getPageLimit(); assertEquals("Getter did not return set value", value, actual); } @@ -161,6 +171,7 @@ public class AbstractContentTransformerLimitsTest addMimetypeLimits(A, B, limits); transformer.setMimetypeLimits(mimetypeLimits); + transformer.register(); long actual = transformer.getLimits(A, B, options).getMaxSourceSizeKBytes(); assertEquals("Getter did not return set value", value, actual); @@ -176,6 +187,7 @@ public class AbstractContentTransformerLimitsTest addMimetypeLimits(A, "*", limits); transformer.setMimetypeLimits(mimetypeLimits); + transformer.register(); long actual = transformer.getLimits(A, B, options).getMaxSourceSizeKBytes(); assertEquals("Getter did not return set value", value, actual); @@ -191,6 +203,7 @@ public class AbstractContentTransformerLimitsTest addMimetypeLimits("*", B, limits); transformer.setMimetypeLimits(mimetypeLimits); + transformer.register(); long actual = transformer.getLimits(A, B, options).getMaxSourceSizeKBytes(); assertEquals("Getter did not return set value", value, actual); @@ -206,6 +219,7 @@ public class AbstractContentTransformerLimitsTest addMimetypeLimits(A, B, limits); transformer.setMimetypeLimits(mimetypeLimits); + transformer.register(); long actual = transformer.getLimits(A, B, options).getMaxSourceSizeKBytes(); assertEquals("Getter did not return set value", value+1, actual); @@ -228,6 +242,7 @@ public class AbstractContentTransformerLimitsTest limits.setMaxSourceSizeKBytes(kValue); addMimetypeLimits(A, B, limits); transformer.setMimetypeLimits(mimetypeLimits); + transformer.register(); assertEquals("Expected to have set value returned", kValue, transformer.getMaxSourceSizeKBytes(A, B, options)); @@ -235,51 +250,115 @@ public class AbstractContentTransformerLimitsTest // With a mimetype that does not have any specific limits assertEquals("Expected to have -1 (unlimited) returned", -1, transformer.getMaxSourceSizeKBytes(C, B, options)); + } + + @Test + // Combination using just transformer limit to start with + public void testGetMaxSourceSizeKBytesCombination() throws Exception + { + long kValue = 12; + long byteValue = kValue*1024; - - // Clear the mimetype limits and double check - limits.setMaxSourceSizeKBytes(-1); - - assertEquals("Expected to have -1 (unlimited) returned", -1, - transformer.getMaxSourceSizeKBytes(A, B, options)); + // Not set mimetype limits yet + assertTrue("No limits so should have been ok", + transformer.isTransformableSize(A, byteValue+1, B, options)); // Check for combinations with transformer limits - // a) Using just transformer limit to start with transformer.setMaxSourceSizeKBytes(kValue); + transformer.register(); assertEquals("Expected to have transformer set value returned", kValue, transformer.getMaxSourceSizeKBytes(A, B, options)); + } - // b) combination where transformer limit is used + @Test + // Combination where transformer limit is used + public void testGetMaxSourceSizeKBytesCombinationTransUsed() throws Exception + { + long kValue = 12; + long byteValue = kValue*1024; + + // Not set mimetype limits yet + assertTrue("No limits so should have been ok", + transformer.isTransformableSize(A, byteValue+1, B, options)); + transformer.setMaxSourceSizeKBytes(kValue); limits.setMaxSourceSizeKBytes(kValue+1); + addMimetypeLimits(A, B, limits); + transformer.setMimetypeLimits(mimetypeLimits); + transformer.register(); assertEquals("Expected to have transformer set value returned", kValue, transformer.getMaxSourceSizeKBytes(A, B, options)); - - // c) combination where mimetype limit is used + } + + @Test + // Combination where mimetype limit is used + public void testGetMaxSourceSizeKBytesCombinationMimetypeUsed() throws Exception + { + long kValue = 12; + long byteValue = kValue*1024; + + // Not set mimetype limits yet + assertTrue("No limits so should have been ok", + transformer.isTransformableSize(A, byteValue+1, B, options)); + transformer.setMaxSourceSizeKBytes(kValue+1); limits.setMaxSourceSizeKBytes(kValue); + addMimetypeLimits(A, B, limits); + transformer.setMimetypeLimits(mimetypeLimits); + transformer.register(); assertEquals("Expected to have transformer set value returned", kValue, transformer.getMaxSourceSizeKBytes(A, B, options)); + } + + @Test + // Check no limit when page limit set on a transformer that does not support page limit + // maxSourceSizeKbytes value should be ignored if a page limit is in use + public void testGetMaxSourceSizeKBytesPageSupportsNot() throws Exception + { + long kValue = 12; + long byteValue = kValue*1024; - // Check no limit when page limit set on a transformer that does not support page limit + // Not set mimetype limits yet + assertTrue("No limits so should have been ok", + transformer.isTransformableSize(A, byteValue+1, B, options)); + + transformer.setPageLimitsSuported(false); transformer.setMaxSourceSizeKBytes(kValue); limits.setMaxSourceSizeKBytes(kValue+1); limits.setPageLimit(1); + addMimetypeLimits(A, B, limits); + transformer.setMimetypeLimits(mimetypeLimits); + transformer.register(); assertEquals("Expected to ignore the page limit as the transformer does not support it", kValue, transformer.getMaxSourceSizeKBytes(A, B, options)); + } + @Test + // Check no limit when page limit set on a transformer that does support page limit + // maxSourceSizeKbytes value should be ignored if a page limit is in use + public void testGetMaxSourceSizeKBytesPageSupports() throws Exception + { + long kValue = 12; + long byteValue = kValue*1024; - // Check no limit when page limit set on a transformer that does support page limit + // Not set mimetype limits yet + assertTrue("No limits so should have been ok", + transformer.isTransformableSize(A, byteValue+1, B, options)); + + transformer.setPageLimitsSuported(true); transformer.setMaxSourceSizeKBytes(kValue); limits.setMaxSourceSizeKBytes(kValue+1); - transformer.setPageLimitsSuported(true); limits.setPageLimit(1); + addMimetypeLimits(A, B, limits); + transformer.setMimetypeLimits(mimetypeLimits); + transformer.register(); assertEquals("Expected to have -1 (unlimited) returned when there are page limits", -1, transformer.getMaxSourceSizeKBytes(A, B, options)); } @Test - public void testIsTransformableSize() throws Exception + // Using limit on a mimetype + public void testIsTransformableSizeMimetype() throws Exception { long kValue = 12; long byteValue = kValue*1024; @@ -292,12 +371,13 @@ public class AbstractContentTransformerLimitsTest limits.setMaxSourceSizeKBytes(kValue); addMimetypeLimits(A, B, limits); transformer.setMimetypeLimits(mimetypeLimits); + transformer.register(); assertTrue("Size is less than limit so should have been ok", transformer.isTransformableSize(A, byteValue-1, B, options)); assertTrue("Size is equal to limit so should have been ok", transformer.isTransformableSize(A, byteValue, B, options)); - assertFalse("Size is greater than limit so should not have failed", + assertFalse("Size is greater than limit so should have failed", transformer.isTransformableSize(A, byteValue+1, B, options)); // With a mimetype that does not have any specific limits @@ -307,36 +387,68 @@ public class AbstractContentTransformerLimitsTest transformer.isTransformableSize(A, byteValue+1, C, options)); assertTrue("No limits so should have been ok", transformer.isTransformableSize(C, byteValue+1, C, options)); - - // Clear the mimetype limits and double check - limits.setMaxSourceSizeKBytes(-1); - + } + + @Test + // Using limit on transformer as a whole + public void testIsTransformableSizeTrans() throws Exception + { + long kValue = 12; + long byteValue = kValue*1024; + + // Not set mimetype limits yet assertTrue("No limits so should have been ok", transformer.isTransformableSize(A, byteValue+1, B, options)); - // Check for combinations with transformer limits - - // a) Using just transformer limit to start with transformer.setMaxSourceSizeKBytes(kValue); + transformer.register(); assertTrue("Size is equal to limit so should have been ok", transformer.isTransformableSize(A, byteValue, B, options)); - assertFalse("Size is greater than limit so should not have failed", + assertFalse("Size is greater than limit so should have failed", transformer.isTransformableSize(A, byteValue+1, B, options)); + } - // b) combination where transformer limit is used + @Test + // Combination where transformer limit is used + public void testIsTransformableSizeCombinationTransUsed() throws Exception + { + long kValue = 12; + long byteValue = kValue*1024; + + // Not set mimetype limits yet + assertTrue("No limits so should have been ok", + transformer.isTransformableSize(A, byteValue+1, B, options)); + transformer.setMaxSourceSizeKBytes(kValue); limits.setMaxSourceSizeKBytes(kValue+1); + addMimetypeLimits(A, B, limits); + transformer.setMimetypeLimits(mimetypeLimits); + transformer.register(); assertTrue("Size is equal to limit so should have been ok", transformer.isTransformableSize(A, byteValue, B, options)); - assertFalse("Size is greater than limit so should not have failed", + assertFalse("Size is greater than limit so should have failed", transformer.isTransformableSize(A, byteValue+1, B, options)); + } - // c) combination where mimetype limit is used + @Test + // Combination where mimetype limit is used + public void testIsTransformableSizeCombinationMimetypeUsed() throws Exception + { + long kValue = 12; + long byteValue = kValue*1024; + + // Not set mimetype limits yet + assertTrue("No limits so should have been ok", + transformer.isTransformableSize(A, byteValue+1, B, options)); + transformer.setMaxSourceSizeKBytes(kValue+1); limits.setMaxSourceSizeKBytes(kValue); + addMimetypeLimits(A, B, limits); + transformer.setMimetypeLimits(mimetypeLimits); + transformer.register(); assertTrue("Size is equal to limit so should have been ok", transformer.isTransformableSize(A, byteValue, B, options)); - assertFalse("Size is greater than limit so should not have failed", + assertFalse("Size is greater than limit so should have failed", transformer.isTransformableSize(A, byteValue+1, B, options)); } @@ -348,6 +460,7 @@ public class AbstractContentTransformerLimitsTest transformer.setMaxSourceSizeKBytes(kValue); transformer.setPageLimitsSuported(true); + transformer.register(); // Test works as normal before setting the pageLimit assertTrue("Size is less than limit so should have been ok", @@ -370,6 +483,7 @@ public class AbstractContentTransformerLimitsTest long value = 1234; transformer.setTimeoutMs(value); + transformer.register(); assertEquals("Limit should not have been set in the reader", null, reader.getLimits()); diff --git a/source/java/org/alfresco/repo/content/transform/AbstractContentTransformerTest.java b/source/java/org/alfresco/repo/content/transform/AbstractContentTransformerTest.java index c078ac9b1a..e8faadb083 100644 --- a/source/java/org/alfresco/repo/content/transform/AbstractContentTransformerTest.java +++ b/source/java/org/alfresco/repo/content/transform/AbstractContentTransformerTest.java @@ -70,6 +70,7 @@ public abstract class AbstractContentTransformerTest extends TestCase protected ServiceRegistry serviceRegistry; protected MimetypeService mimetypeService; protected TransformerDebug transformerDebug; + protected TransformerConfig transformerConfig; /** * Fetches a transformer to test for a given transformation. The transformer @@ -97,6 +98,8 @@ public abstract class AbstractContentTransformerTest extends TestCase serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY); mimetypeService = serviceRegistry.getMimetypeService(); transformerDebug = (TransformerDebug) ctx.getBean("transformerDebug"); + transformerConfig = (TransformerConfig) ctx.getBean("transformerConfig"); + // perform a little cleaning up long now = System.currentTimeMillis(); TempFileProvider.TempFileCleanerJob.removeFiles(now); diff --git a/source/java/org/alfresco/repo/content/transform/AppleIWorksContentTransformerTest.java b/source/java/org/alfresco/repo/content/transform/AppleIWorksContentTransformerTest.java index be25a8ba51..eb8b09822b 100644 --- a/source/java/org/alfresco/repo/content/transform/AppleIWorksContentTransformerTest.java +++ b/source/java/org/alfresco/repo/content/transform/AppleIWorksContentTransformerTest.java @@ -40,6 +40,7 @@ public class AppleIWorksContentTransformerTest extends AbstractContentTransforme // Ugly cast just to set the MimetypeService ((ContentTransformerHelper)transformer).setMimetypeService(mimetypeService); + ((ContentTransformerHelper)transformer).setTransformerConfig(transformerConfig); } @Override diff --git a/source/java/org/alfresco/repo/content/transform/ArchiveContentTransformerTest.java b/source/java/org/alfresco/repo/content/transform/ArchiveContentTransformerTest.java index 880f7febdf..def6934867 100644 --- a/source/java/org/alfresco/repo/content/transform/ArchiveContentTransformerTest.java +++ b/source/java/org/alfresco/repo/content/transform/ArchiveContentTransformerTest.java @@ -47,6 +47,7 @@ public class ArchiveContentTransformerTest extends AbstractContentTransformerTes transformer = new ArchiveContentTransformer(); transformer.setMimetypeService(mimetypeService); transformer.setTransformerDebug(transformerDebug); + transformer.setTransformerConfig(transformerConfig); } protected ContentTransformer getTransformer(String sourceMimetype, String targetMimetype) diff --git a/source/java/org/alfresco/repo/content/transform/BinaryPassThroughContentTransformerTest.java b/source/java/org/alfresco/repo/content/transform/BinaryPassThroughContentTransformerTest.java index 565251833e..b0d88bacd8 100644 --- a/source/java/org/alfresco/repo/content/transform/BinaryPassThroughContentTransformerTest.java +++ b/source/java/org/alfresco/repo/content/transform/BinaryPassThroughContentTransformerTest.java @@ -38,6 +38,7 @@ public class BinaryPassThroughContentTransformerTest extends AbstractContentTran transformer = new BinaryPassThroughContentTransformer(); transformer.setMimetypeService(mimetypeService); transformer.setTransformerDebug(transformerDebug); + transformer.setTransformerConfig(transformerConfig); } /** diff --git a/source/java/org/alfresco/repo/content/transform/ComplexContentTransformer.java b/source/java/org/alfresco/repo/content/transform/ComplexContentTransformer.java index 55a1364c7e..68055c1728 100644 --- a/source/java/org/alfresco/repo/content/transform/ComplexContentTransformer.java +++ b/source/java/org/alfresco/repo/content/transform/ComplexContentTransformer.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2012 Alfresco Software Limited. + * Copyright (C) 2005-2013 Alfresco Software Limited. * * This file is part of Alfresco * @@ -267,7 +267,7 @@ public class ComplexContentTransformer extends AbstractContentTransformer2 imple transformer = transformerIterator.next(); if (transformer != null) { - if (transformer.isTransformableMimetype(sourceMimetype, targetMimetype, options)) + if (transformer.isTransformable(sourceMimetype, -1, targetMimetype, options)) { return false; } @@ -306,7 +306,7 @@ public class ComplexContentTransformer extends AbstractContentTransformer2 imple } else { - if (transformer.isTransformableMimetype(currentSourceMimetype, currentTargetMimetype, options) == false) + if (transformer.isTransformable(currentSourceMimetype, -1, currentTargetMimetype, options) == false) { result = false; break; diff --git a/source/java/org/alfresco/repo/content/transform/ComplexContentTransformerTest.java b/source/java/org/alfresco/repo/content/transform/ComplexContentTransformerTest.java index 6316d101cd..b83216f483 100644 --- a/source/java/org/alfresco/repo/content/transform/ComplexContentTransformerTest.java +++ b/source/java/org/alfresco/repo/content/transform/ComplexContentTransformerTest.java @@ -63,6 +63,7 @@ public class ComplexContentTransformerTest extends AbstractContentTransformerTes transformer = new ComplexContentTransformer(); transformer.setMimetypeService(mimetypeService); transformer.setTransformerDebug(transformerDebug); + transformer.setTransformerConfig(transformerConfig); // set the transformer list List transformers = new ArrayList(2); transformers.add(unoTransformer); diff --git a/source/java/org/alfresco/repo/content/transform/ContentTransformer.java b/source/java/org/alfresco/repo/content/transform/ContentTransformer.java index e683b88dbf..200db7ab86 100644 --- a/source/java/org/alfresco/repo/content/transform/ContentTransformer.java +++ b/source/java/org/alfresco/repo/content/transform/ContentTransformer.java @@ -78,29 +78,39 @@ public interface ContentTransformer extends ContentWorker public long getMaxSourceSizeKBytes(String sourceMimetype, String targetMimetype, TransformationOptions options); /** - * Indicates whether given the provided transformation parmaters this transformer can prvide an explict + * @deprecated Use transformer priority and unsupported transformer properties. + * + * Indicates whether given the provided transformation parameters this transformer can provide an explicit * transformation. * - * An explict transformation indicates that the transformation happens directly and not as a result of - * another transformation process. Explict transformation always take presidence over normal transformations. + * An explicit transformation indicates that the transformation happens directly and not as a result of + * another transformation process. Explicit transformation always take presidency over normal transformations. * * @param sourceMimetype the source mimetype * @param targetMimetype the target mimetype * @param options the transformation options - * @return boolean true if it is an explicit transformation, flase otherwise + * @return boolean true if it is an explicit transformation, false otherwise */ public boolean isExplicitTransformation(String sourceMimetype, String targetMimetype, TransformationOptions options); + /** + * @deprecated use mimetype specific version. + */ + public long getTransformationTime(); + /** * Provides an estimate, usually a worst case guess, of how long a transformation - * will take. + * will take. Null mimetype values provide the overall value for the transformer. *

* This method is used to determine, up front, which of a set of * equally reliant transformers will be used for a specific transformation. * + * @param sourceMimetype the source mimetype + * @param targetMimetype the target mimetype + * * @return Returns the approximate number of milliseconds per transformation */ - public long getTransformationTime(); + public long getTransformationTime(String sourceMimetype, String targetMimetype); /** * @see #transform(ContentReader, ContentWriter, TransformationOptions) @@ -157,4 +167,9 @@ public interface ContentTransformer extends ContentWorker */ public void transform(ContentReader reader, ContentWriter contentWriter, TransformationOptions options) throws ContentIOException; + + /** + * Returns transformer's name used in configuration. + */ + public String getName(); } diff --git a/source/java/org/alfresco/repo/content/transform/ContentTransformerHelper.java b/source/java/org/alfresco/repo/content/transform/ContentTransformerHelper.java index c7278c124b..a92cd5e30d 100644 --- a/source/java/org/alfresco/repo/content/transform/ContentTransformerHelper.java +++ b/source/java/org/alfresco/repo/content/transform/ContentTransformerHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2012 Alfresco Software Limited. + * Copyright (C) 2005-2013 Alfresco Software Limited. * * This file is part of Alfresco * @@ -18,37 +18,36 @@ */ package org.alfresco.repo.content.transform; -import java.util.Collections; +import static org.alfresco.repo.content.transform.TransformerConfig.ANY; + +import java.util.ArrayList; import java.util.List; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.service.cmr.repository.ContentAccessor; import org.alfresco.service.cmr.repository.MimetypeService; import org.alfresco.service.cmr.repository.TransformationOptions; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.BeanNameAware; /** - * A class providing basic functionality shared by both {@link ContentTransformer}s and {@link ContentTransformerWorker} - * s. + * A class providing basic functionality shared by both {@link ContentTransformer}s and {@link ContentTransformerWorker}s. * * @author dward */ -public class ContentTransformerHelper +public class ContentTransformerHelper implements BeanNameAware { + private static final Log logger = LogFactory.getLog(ContentTransformerHelper.class); private MimetypeService mimetypeService; - private List explicitTransformations; - private List supportedTransformations; - private List unsupportedTransformations; + protected TransformerConfig transformerConfig; + + private List deprecatedSetterMessages; + private static boolean firstDeprecatedSetter = true; - /** - * - */ - public ContentTransformerHelper() - { - setExplicitTransformations(Collections. emptyList()); - setSupportedTransformations(null); - setUnsupportedTransformations(null); - } + /** The bean name. */ + private String beanName; /** * Helper setter of the mimetype service. This is not always required. @@ -69,37 +68,35 @@ public class ContentTransformerHelper } /** - * Specifies transformations that are considered to be 'exceptional' so - * should be used in preference to other transformers that can perform - * the same transformation. + * @deprecated supported transformations are now set with global properties rather than spring configuration. */ public void setExplicitTransformations(List explicitTransformations) { - this.explicitTransformations = explicitTransformations; + deprecatedSupportedTransformations(explicitTransformations, null); + // TODO Should suggest properties that indicate lower priority transformers should be unsupported. + // This is for completeness rather than needed as the priority will avoid the non explicit + // transformers from being used. Explicit transformers are given a priority of 5 rather than 10. } /** - * Restricts the transformations that may be performed even though the transformer - * may perform other transformations. An null value applies no additional restrictions. - * Even if a list is specified, the - * {@link ContentTransformer#isTransformableMimetype(String, String, TransformationOptions)} - * method will still be called. + * @deprecated supported transformations are now set with global properties rather than spring configuration. */ public void setSupportedTransformations(List supportedTransformations) { - this.supportedTransformations = supportedTransformations; + deprecatedSupportedTransformations(supportedTransformations, "true"); } /** - * Restricts the transformations that may be performed even though the transformer - * may claim to perform the transformations. An null value applies no additional restrictions. - * Even if a list is specified, the - * {@link ContentTransformer#isTransformableMimetype(String, String, TransformationOptions)} - * method will still be called. + * @deprecated supported transformations are now set with global properties rather than spring configuration. */ public void setUnsupportedTransformations(List unsupportedTransformations) { - this.unsupportedTransformations = unsupportedTransformations; + deprecatedSupportedTransformations(unsupportedTransformations, "false"); + } + + public void setTransformerConfig(TransformerConfig transformerConfig) + { + this.transformerConfig = transformerConfig; } /** @@ -123,58 +120,138 @@ public class ContentTransformerHelper } /** - * Default implementation, override if need to extend logic + * @deprecated Should now use priority and unsupported transformer properties. * * @see org.alfresco.repo.content.transform.ContentTransformer#isExplicitTransformation(java.lang.String, * java.lang.String, org.alfresco.service.cmr.repository.TransformationOptions) */ public boolean isExplicitTransformation(String sourceMimetype, String targetMimetype, TransformationOptions options) { - boolean result = false; - for (ExplictTransformationDetails explicitTransformation : this.explicitTransformations) - { - if (sourceMimetype.equals(explicitTransformation.getSourceMimetype()) == true - && targetMimetype.equals(explicitTransformation.getTargetMimetype()) == true) - { - result = true; - break; - } - } - return result; + return transformerConfig.getPriority(((ContentTransformer)this), sourceMimetype, targetMimetype) == TransformerConfig.PRIORITY_EXPLICIT; } public boolean isSupportedTransformation(String sourceMimetype, String targetMimetype, TransformationOptions options) { - boolean supported = true; - if (supportedTransformations != null) + return transformerConfig.isSupportedTransformation(((ContentTransformer)this), sourceMimetype, targetMimetype, options); + } + + /** + * Sets the Spring bean name. + */ + @Override + public void setBeanName(String beanName) + { + this.beanName = beanName; + } + + /** + * THIS IS A CUSTOM SPRING INIT METHOD + */ + public void register() + { + logDeprecatedSetter(); + } + + /** + * Returns the Spring bean name. + */ + public String getBeanName() + { + return beanName; + } + + /** + * Returns transformer name. Uses the Spring bean name, but if null uses the class name. + */ + public String getName() + { + return (beanName == null) ? getClass().getSimpleName() : beanName; + } + + /** + * Called by deprecated property setter methods that should no longer be called + * by Spring configuration as the values are now set using global properties. + * @param suffixAndValue that should have been used. The first part of the + * property name "content.transformer.." should not be included. + * The reason is that the setter methods might be called before the bean + * name is set. + */ + protected void deprecatedSetter(String suffixAndValue) + { + if (deprecatedSetterMessages == null) { - supported = false; - for (SupportedTransformation suportedTransformation : supportedTransformations) + deprecatedSetterMessages = new ArrayList(); + } + deprecatedSetterMessages.add(suffixAndValue); + } + + /** + * Called when the bean name is set after all the deprecated setters to log + * INFO messages with the Alfresco global properties that should now be set + * (if no set) to replace Spring configuration. + */ + private void logDeprecatedSetter() + { + if (deprecatedSetterMessages != null) + { + for (String suffixAndValue: deprecatedSetterMessages) { - String supportedSourceMimetype = suportedTransformation.getSourceMimetype(); - String supportedTargetMimetype = suportedTransformation.getTargetMimetype(); - if ((supportedSourceMimetype == null || sourceMimetype.equals(supportedSourceMimetype)) && - (supportedTargetMimetype == null || targetMimetype.equals(supportedTargetMimetype))) + String propertyNameAndValue = TransformerConfig.CONTENT+beanName+'.'+suffixAndValue; + String propertyName = propertyNameAndValue.replaceAll("=.*", ""); + if (transformerConfig.getProperty(propertyName) == null) { - supported = true; - break; + if (firstDeprecatedSetter) + { + firstDeprecatedSetter = false; + logger.error("In order to support dynamic setting of transformer options, Spring XML configuration"); + logger.error("is no longer used to initialise these options."); + logger.error(" "); + logger.error("Your system appears to contains custom Spring configuration which should be replace by"); + logger.error("the following Alfresco global properties. In the case of the Enterprise edition these"); + logger.error("values may then be dynamically changed via JMX."); + logger.error(" "); + // Note: Cannot set these automatically because, an MBean reset would clear them. + } + logger.error(propertyNameAndValue); + + // Add them to the subsystem's properties anyway (even though an MBean reset would clear them), + // so that existing unit tests work. + transformerConfig.setProperty(propertyNameAndValue); + } + else + { + logger.warn(propertyNameAndValue+" is set, but spring config still exists"); } } + deprecatedSetterMessages = null; } - if (supported && unsupportedTransformations != null) + } + + private void deprecatedSupportedTransformations(List transformations, String value) + { + if (transformations != null) { - for (SupportedTransformation unsuportedTransformation : unsupportedTransformations) + for (SupportedTransformation transformation: transformations) { - String unsupportedSourceMimetype = unsuportedTransformation.getSourceMimetype(); - String unsupportedTargetMimetype = unsuportedTransformation.getTargetMimetype(); - if ((unsupportedSourceMimetype == null || sourceMimetype.equals(unsupportedSourceMimetype)) && - (unsupportedTargetMimetype == null || targetMimetype.equals(unsupportedTargetMimetype))) - { - supported = false; - break; - } + String sourceMimetype = transformation.getSourceMimetype(); + String targetMimetype = transformation.getTargetMimetype(); + String sourceExt = getExtensionOrAny(sourceMimetype); + String targetExt = getExtensionOrAny(targetMimetype); + deprecatedSetter(TransformerConfig.MIMETYPES_SEPARATOR.substring(1)+sourceExt+'.'+targetExt+ + (value == null // same as: transformation instanceof ExplictTransformationDetails + ? TransformerConfig.PRIORITY+"="+TransformerConfig.PRIORITY_EXPLICIT + : TransformerConfig.SUPPORTED+"="+value)); } } - return supported; + } + + protected String getExtensionOrAny(String mimetype) + { + return mimetype == null || ANY.equals(mimetype) ? ANY : mimetypeService.getExtension(mimetype); + } + + public String toString() + { + return getName(); } } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/content/transform/ContentTransformerRegistry.java b/source/java/org/alfresco/repo/content/transform/ContentTransformerRegistry.java index 66ea3e89cd..f796060704 100644 --- a/source/java/org/alfresco/repo/content/transform/ContentTransformerRegistry.java +++ b/source/java/org/alfresco/repo/content/transform/ContentTransformerRegistry.java @@ -57,7 +57,7 @@ public class ContentTransformerRegistry public ContentTransformerRegistry(TransformerSelector transformerSelector) { this.transformerSelector = transformerSelector; - this.transformers = new ArrayList(10); + this.transformers = new ArrayList(70); } /** @@ -114,7 +114,7 @@ public class ContentTransformerRegistry public List getActiveTransformers(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options) { // Get the list of transformers - List transformers = transformerSelector.selectTransformers(this.transformers, sourceMimetype, sourceSize, targetMimetype, options); + List transformers = transformerSelector.selectTransformers(sourceMimetype, sourceSize, targetMimetype, options); if (logger.isDebugEnabled()) { logger.debug("Searched for transformer: \n" + diff --git a/source/java/org/alfresco/repo/content/transform/ContentTransformerRegistryTest.java b/source/java/org/alfresco/repo/content/transform/ContentTransformerRegistryTest.java index c3bd6b9b61..590d1a1b08 100644 --- a/source/java/org/alfresco/repo/content/transform/ContentTransformerRegistryTest.java +++ b/source/java/org/alfresco/repo/content/transform/ContentTransformerRegistryTest.java @@ -52,6 +52,12 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe private ContentReader reader; private ContentWriter writer; + private DummyTransformer ad20; + private DummyTransformer ad30; + private DummyTransformer ad10; + private DummyTransformer ad25a; + private DummyTransformer ad25b; + @Override public void setUp() throws Exception { @@ -70,19 +76,23 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe bytes[i] = (byte)i; } // create the dummyRegistry - dummyRegistry = new ContentTransformerRegistry(new TransformerSelectorImpl()); + TransformerSelectorImpl transformerSelector = new TransformerSelectorImpl(); + transformerSelector.setTransformerConfig(transformerConfig); + transformerSelector.setContentTransformerRegistry(dummyRegistry); + dummyRegistry = new ContentTransformerRegistry(transformerSelector); + transformerSelector.setContentTransformerRegistry(dummyRegistry); // create some dummy transformers for reliability tests - new DummyTransformer(mimetypeService, transformerDebug, dummyRegistry, A, B, 10L); - new DummyTransformer(mimetypeService, transformerDebug, dummyRegistry, A, B, 10L); - new DummyTransformer(mimetypeService, transformerDebug, dummyRegistry, A, C, 10L); - new DummyTransformer(mimetypeService, transformerDebug, dummyRegistry, A, C, 10L); - new DummyTransformer(mimetypeService, transformerDebug, dummyRegistry, B, C, 10L); + new DummyTransformer(mimetypeService, "transformer.testAB10a", transformerDebug, transformerConfig, dummyRegistry, A, B, 10L); + new DummyTransformer(mimetypeService, "transformer.testAB10b", transformerDebug, transformerConfig, dummyRegistry, A, B, 10L); + new DummyTransformer(mimetypeService, "transformer.testAC10a", transformerDebug, transformerConfig, dummyRegistry, A, C, 10L); + new DummyTransformer(mimetypeService, "transformer.testAC10b", transformerDebug, transformerConfig, dummyRegistry, A, C, 10L); + new DummyTransformer(mimetypeService, "transformer.testBC10", transformerDebug, transformerConfig, dummyRegistry, B, C, 10L); // create some dummy transformers for speed tests - new DummyTransformer(mimetypeService, transformerDebug, dummyRegistry, A, D, 20L); - new DummyTransformer(mimetypeService, transformerDebug, dummyRegistry, A, D, 30L); - new DummyTransformer(mimetypeService, transformerDebug, dummyRegistry, A, D, 10L); // the fast one - new DummyTransformer(mimetypeService, transformerDebug, dummyRegistry, A, D, 25L); - new DummyTransformer(mimetypeService, transformerDebug, dummyRegistry, A, D, 25L); + ad20 = new DummyTransformer(mimetypeService, "transformer.testAD20", transformerDebug, transformerConfig, dummyRegistry, A, D, 20L); + ad30 = new DummyTransformer(mimetypeService, "transformer.testAD30", transformerDebug, transformerConfig, dummyRegistry, A, D, 30L); + ad10 = new DummyTransformer(mimetypeService, "transformer.testAD10", transformerDebug, transformerConfig, dummyRegistry, A, D, 10L); // the fast one + ad25a = new DummyTransformer(mimetypeService, "transformer.testAD25a", transformerDebug, transformerConfig, dummyRegistry, A, D, 25L); + ad25b = new DummyTransformer(mimetypeService, "transformer.testAD25b", transformerDebug, transformerConfig, dummyRegistry, A, D, 25L); } /** @@ -131,20 +141,45 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe */ public void testPerformanceRetrieval() throws Exception { + // Until the threshold (3) is reached by each transformer with the same priority it will + // be tried that many times in the order defined. 20, 30, 10, 25, 25 + for (int i=1; i<=3; i++) + { + long expectedTime = i == 1 ? 0L : 20L; + ContentTransformer transformer1 = dummyRegistry.getTransformer(A, -1, D, OPTIONS); + assertEquals(i+" incorrect transformation time", expectedTime, transformer1.getTransformationTime(A, D)); + ad20.transformInternal(null, null, null); + } + for (int i=1; i<=3; i++) + { + long expectedTime = i == 1 ? 0L : 30L; + ContentTransformer transformer1 = dummyRegistry.getTransformer(A, -1, D, OPTIONS); + assertEquals(i+" incorrect transformation time", expectedTime, transformer1.getTransformationTime(A, D)); + ad30.transformInternal(null, null, null); + } + for (int i=1; i<=3; i++) + { + ad10.transformInternal(null, null, null); + ad25a.transformInternal(null, null, null); + ad25b.transformInternal(null, null, null); + } + + // Now the average times are set up, it should find the fastest one + // A -> D expect 1.0, 10ms ContentTransformer transformer1 = dummyRegistry.getTransformer(A, -1, D, OPTIONS); assertTrue("Incorrect reliability", transformer1.isTransformable(A, -1, D, OPTIONS)); assertFalse("Incorrect reliability", transformer1.isTransformable(D, -1, A, OPTIONS)); - assertEquals("Incorrect transformation time", 10L, transformer1.getTransformationTime()); + assertEquals("Incorrect transformation time", 10L, transformer1.getTransformationTime(A, D)); // A -> D has 10, 20, 25, 25, 30 List activeTransformers = dummyRegistry.getActiveTransformers(A, -1, D, OPTIONS); assertEquals("Not all found", 5, activeTransformers.size()); - assertEquals("Incorrect order", 10L, activeTransformers.get(0).getTransformationTime()); - assertEquals("Incorrect order", 20L, activeTransformers.get(1).getTransformationTime()); - assertEquals("Incorrect order", 25L, activeTransformers.get(2).getTransformationTime()); - assertEquals("Incorrect order", 25L, activeTransformers.get(3).getTransformationTime()); - assertEquals("Incorrect order", 30L, activeTransformers.get(4).getTransformationTime()); + assertEquals("Incorrect order", 10L, activeTransformers.get(0).getTransformationTime(A, D)); + assertEquals("Incorrect order", 20L, activeTransformers.get(1).getTransformationTime(A, D)); + assertEquals("Incorrect order", 25L, activeTransformers.get(2).getTransformationTime(A, D)); + assertEquals("Incorrect order", 25L, activeTransformers.get(3).getTransformationTime(A, D)); + assertEquals("Incorrect order", 30L, activeTransformers.get(4).getTransformationTime(A, D)); // Disable two of them, and re-test ((DummyTransformer)activeTransformers.get(2)).disable(); @@ -152,9 +187,9 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe activeTransformers = dummyRegistry.getActiveTransformers(A, -1, D, OPTIONS); assertEquals("Not all found", 3, activeTransformers.size()); - assertEquals("Incorrect order", 10L, activeTransformers.get(0).getTransformationTime()); - assertEquals("Incorrect order", 20L, activeTransformers.get(1).getTransformationTime()); - assertEquals("Incorrect order", 25L, activeTransformers.get(2).getTransformationTime()); + assertEquals("Incorrect order", 10L, activeTransformers.get(0).getTransformationTime(A, D)); + assertEquals("Incorrect order", 20L, activeTransformers.get(1).getTransformationTime(A, D)); + assertEquals("Incorrect order", 25L, activeTransformers.get(2).getTransformationTime(A, D)); } public void testScoredRetrieval() throws Exception @@ -180,9 +215,9 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe { AbstractContentTransformer2 dummyTransformer = new DummyTransformer( mimetypeService, - transformerDebug, - dummyRegistry, MimetypeMap.MIMETYPE_FLASH, - MimetypeMap.MIMETYPE_EXCEL, 12345); + "transformer.testExplicit", + transformerDebug, transformerConfig, + dummyRegistry, MimetypeMap.MIMETYPE_FLASH, MimetypeMap.MIMETYPE_EXCEL, 12345); // set an explicit transformation ExplictTransformationDetails key = new ExplictTransformationDetails( @@ -212,25 +247,23 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe public DummyTransformer( MimetypeService mimetypeService, - TransformerDebug transformerDebug, - ContentTransformerRegistry registry, String sourceMimetype, - String targetMimetype, long transformationTime) + String name, + TransformerDebug transformerDebug, TransformerConfig transformerConfig, + ContentTransformerRegistry registry, String sourceMimetype, String targetMimetype, long transformationTime) { super.setMimetypeService(mimetypeService); super.setTransformerDebug(transformerDebug); + super.setTransformerConfig(transformerConfig); super.setRegistry(registry); this.sourceMimetype = sourceMimetype; this.targetMimetype = targetMimetype; this.transformationTime = transformationTime; + setBeanName(name+'.'+System.currentTimeMillis()%100000); + // register register(); } - protected void enable() - { - disable = false; - } - protected void disable() { disable = true; @@ -262,16 +295,16 @@ public class ContentTransformerRegistryTest extends AbstractContentTransformerTe TransformationOptions options) throws Exception { // just update the transformation time - super.recordTime(transformationTime); + super.recordTime(sourceMimetype, targetMimetype, transformationTime); } - /** - * @return Returns the fixed dummy average transformation time - */ - public synchronized long getTransformationTime() - { - return transformationTime; - } +// /** +// * @return Returns the fixed dummy average transformation time +// */ +// public synchronized long getTransformationTime(String sourceMimetype, String targetMimetype) +// { +// return transformationTime; +// } } @Override diff --git a/source/java/org/alfresco/repo/content/transform/DoubleMap.java b/source/java/org/alfresco/repo/content/transform/DoubleMap.java new file mode 100644 index 0000000000..6f8fd306b6 --- /dev/null +++ b/source/java/org/alfresco/repo/content/transform/DoubleMap.java @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2005-2012 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco 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 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Alfresco. If not, see . + */ +package org.alfresco.repo.content.transform; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Provides simple get and put access to a Map like object with a double key that allows + * either or both keys to be a wild card that matches any value. May not contain null + * keys or values.

+ * + * Originally created for mapping source and target mimetypes to transformer configuration data.

+ * + * For example: + *

+ *       DoubleMap foodLikes = new DoubleMap("*", "*");
+ *       
+ *       foodLikes.put("cat",   "mouse", "likes");
+ *       
+ *       foodLikes.get("cat", "mouse"); // returns "likes"
+ *       foodLikes.get("cat", "meat");  // returns null
+ *       
+ *       foodLikes.put("dog",   "meat",  "likes");
+ *       foodLikes.put("dog",   "stick", "unsure");
+ *       foodLikes.put("child", "olive", "dislikes");
+ *       foodLikes.put("bird",  "*",     "worms only");
+ *       foodLikes.put("*",     "meat",  "unknown");
+ *       foodLikes.put("*",     "*",     "no idea at all");
+ *       
+ *       foodLikes.get("cat", "mouse"); // returns "likes"
+ *       foodLikes.get("cat", "meat");  // returns "unknown"
+ *       foodLikes.get("cat", "tea");   // returns "unknown"
+ *       foodLikes.get("*",   "mouse"); // returns "no idea at all"
+ *       foodLikes.get("dog", "*");     // returns "no idea at all"
+ *       foodLikes.get("bird","*");     // returns "worms only"
+ *       foodLikes.get("bird","tea");   // returns "worms only"
+ * 
+ * + * @author Alan Davis + */ +public class DoubleMap +{ + private final Map> mapMap = new ConcurrentHashMap>(); + private final K1 anyKey1; + private final K2 anyKey2; + + public DoubleMap(K1 anyKey1, K2 anyKey2) + { + this.anyKey1 = anyKey1; + this.anyKey2 = anyKey2; + } + + /** + * Returns a value for the given keys. + */ + public V get(K1 key1, K2 key2) + { + V value = null; + + Map map = mapMap.get(key1); + boolean anySource = false; + if (map == null) + { + map = mapMap.get(anyKey1); + anySource = true; + } + if (map != null) + { + value = map.get(key2); + if (value == null) + { + value = map.get(anyKey2); + + // Handle the case were there is no match using an non wildcarded key1 and + // key2 but is a match if key1 is wildcarded. + if (value == null && !anySource) + { + map = mapMap.get(anyKey1); + if (map != null) + { + value = map.get(key2); + if (value == null) + { + value = map.get(anyKey2); + } + } + } + } + } + + return value; + } + + /** + * Adds a value for the given keys. + */ + public void put(K1 key1, K2 key2, V t) + { + Map map = mapMap.get(key1); + if (map == null) + { + map = new ConcurrentHashMap(); + mapMap.put(key1, map); + } + + map.put(key2, t); + } +} diff --git a/source/java/org/alfresco/repo/content/transform/EMLTransformerTest.java b/source/java/org/alfresco/repo/content/transform/EMLTransformerTest.java index 2eafdb7b67..dbac19f173 100644 --- a/source/java/org/alfresco/repo/content/transform/EMLTransformerTest.java +++ b/source/java/org/alfresco/repo/content/transform/EMLTransformerTest.java @@ -50,6 +50,7 @@ public class EMLTransformerTest extends AbstractContentTransformerTest transformer = new EMLTransformer(); transformer.setMimetypeService(mimetypeService); transformer.setTransformerDebug(transformerDebug); + transformer.setTransformerConfig(transformerConfig); } @Override diff --git a/source/java/org/alfresco/repo/content/transform/FailoverContentTransformerTest.java b/source/java/org/alfresco/repo/content/transform/FailoverContentTransformerTest.java index f55e64aaea..ec70b37776 100644 --- a/source/java/org/alfresco/repo/content/transform/FailoverContentTransformerTest.java +++ b/source/java/org/alfresco/repo/content/transform/FailoverContentTransformerTest.java @@ -57,6 +57,7 @@ public class FailoverContentTransformerTest extends AbstractContentTransformerTe transformer = (FailoverContentTransformer) failoverAppContext.getBean("transformer.failover.Test-FailThenSucceed"); transformer.setMimetypeService(mimetypeService); transformer.setTransformerDebug(transformerDebug); + transformer.setTransformerConfig(transformerConfig); } /** diff --git a/source/java/org/alfresco/repo/content/transform/HtmlParserContentTransformerTest.java b/source/java/org/alfresco/repo/content/transform/HtmlParserContentTransformerTest.java index 1eb6f2cfb0..8c970b472b 100644 --- a/source/java/org/alfresco/repo/content/transform/HtmlParserContentTransformerTest.java +++ b/source/java/org/alfresco/repo/content/transform/HtmlParserContentTransformerTest.java @@ -42,6 +42,7 @@ public class HtmlParserContentTransformerTest extends AbstractContentTransformer transformer = new HtmlParserContentTransformer(); transformer.setMimetypeService(mimetypeService); transformer.setTransformerDebug(transformerDebug); + transformer.setTransformerConfig(transformerConfig); } protected ContentTransformer getTransformer(String sourceMimetype, String targetMimetype) diff --git a/source/java/org/alfresco/repo/content/transform/MailContentTransformerTest.java b/source/java/org/alfresco/repo/content/transform/MailContentTransformerTest.java index 3b410590f1..b847812de2 100644 --- a/source/java/org/alfresco/repo/content/transform/MailContentTransformerTest.java +++ b/source/java/org/alfresco/repo/content/transform/MailContentTransformerTest.java @@ -45,6 +45,7 @@ public class MailContentTransformerTest extends AbstractContentTransformerTest transformer = new MailContentTransformer(); transformer.setMimetypeService(mimetypeService); transformer.setTransformerDebug(transformerDebug); + transformer.setTransformerConfig(transformerConfig); } /** diff --git a/source/java/org/alfresco/repo/content/transform/MediaWikiContentTransformerTest.java b/source/java/org/alfresco/repo/content/transform/MediaWikiContentTransformerTest.java index eb7ba7215c..7c97c24860 100644 --- a/source/java/org/alfresco/repo/content/transform/MediaWikiContentTransformerTest.java +++ b/source/java/org/alfresco/repo/content/transform/MediaWikiContentTransformerTest.java @@ -70,6 +70,7 @@ public class MediaWikiContentTransformerTest extends AbstractContentTransformerT transformer = new MediaWikiContentTransformer(); transformer.setMimetypeService(mimetypeService); transformer.setTransformerDebug(transformerDebug); + transformer.setTransformerConfig(transformerConfig); } protected ContentTransformer getTransformer(String sourceMimetype, String targetMimetype) diff --git a/source/java/org/alfresco/repo/content/transform/OpenOfficeContentTransformerTest.java b/source/java/org/alfresco/repo/content/transform/OpenOfficeContentTransformerTest.java index d3728cb03c..31f113c331 100644 --- a/source/java/org/alfresco/repo/content/transform/OpenOfficeContentTransformerTest.java +++ b/source/java/org/alfresco/repo/content/transform/OpenOfficeContentTransformerTest.java @@ -50,6 +50,7 @@ public class OpenOfficeContentTransformerTest extends AbstractContentTransformer transformer = new ProxyContentTransformer(); transformer.setMimetypeService(mimetypeService); transformer.setTransformerDebug(transformerDebug); + transformer.setTransformerConfig(transformerConfig); transformer.setWorker(this.worker); } diff --git a/source/java/org/alfresco/repo/content/transform/PdfBoxContentTransformerTest.java b/source/java/org/alfresco/repo/content/transform/PdfBoxContentTransformerTest.java index d83eae72b3..facbe456d2 100644 --- a/source/java/org/alfresco/repo/content/transform/PdfBoxContentTransformerTest.java +++ b/source/java/org/alfresco/repo/content/transform/PdfBoxContentTransformerTest.java @@ -38,6 +38,7 @@ public class PdfBoxContentTransformerTest extends AbstractContentTransformerTest transformer = new PdfBoxContentTransformer(); transformer.setMimetypeService(mimetypeService); transformer.setTransformerDebug(transformerDebug); + transformer.setTransformerConfig(transformerConfig); } /** diff --git a/source/java/org/alfresco/repo/content/transform/PoiContentTransformerTest.java b/source/java/org/alfresco/repo/content/transform/PoiContentTransformerTest.java index 06386995c6..e4b8ad5832 100644 --- a/source/java/org/alfresco/repo/content/transform/PoiContentTransformerTest.java +++ b/source/java/org/alfresco/repo/content/transform/PoiContentTransformerTest.java @@ -38,6 +38,7 @@ public class PoiContentTransformerTest extends AbstractContentTransformerTest transformer = new PoiContentTransformer(); transformer.setMimetypeService(mimetypeService); transformer.setTransformerDebug(transformerDebug); + transformer.setTransformerConfig(transformerConfig); } /** diff --git a/source/java/org/alfresco/repo/content/transform/PoiHssfContentTransformerTest.java b/source/java/org/alfresco/repo/content/transform/PoiHssfContentTransformerTest.java index 1a8e1ccbfc..df7fc6669d 100644 --- a/source/java/org/alfresco/repo/content/transform/PoiHssfContentTransformerTest.java +++ b/source/java/org/alfresco/repo/content/transform/PoiHssfContentTransformerTest.java @@ -46,6 +46,7 @@ public class PoiHssfContentTransformerTest extends TikaPoweredContentTransformer transformer = new PoiHssfContentTransformer(); transformer.setMimetypeService(mimetypeService); transformer.setTransformerDebug(transformerDebug); + transformer.setTransformerConfig(transformerConfig); } @Override diff --git a/source/java/org/alfresco/repo/content/transform/PoiOOXMLContentTransformerTest.java b/source/java/org/alfresco/repo/content/transform/PoiOOXMLContentTransformerTest.java index 6f29a9a974..56478efa48 100644 --- a/source/java/org/alfresco/repo/content/transform/PoiOOXMLContentTransformerTest.java +++ b/source/java/org/alfresco/repo/content/transform/PoiOOXMLContentTransformerTest.java @@ -38,6 +38,7 @@ public class PoiOOXMLContentTransformerTest extends AbstractContentTransformerTe transformer = new PoiOOXMLContentTransformer(); transformer.setMimetypeService(mimetypeService); transformer.setTransformerDebug(transformerDebug); + transformer.setTransformerConfig(transformerConfig); } /** diff --git a/source/java/org/alfresco/repo/content/transform/RuntimeExecutableContentTransformerTest.java b/source/java/org/alfresco/repo/content/transform/RuntimeExecutableContentTransformerTest.java index 40fdbb8a62..9d6cb4efd0 100644 --- a/source/java/org/alfresco/repo/content/transform/RuntimeExecutableContentTransformerTest.java +++ b/source/java/org/alfresco/repo/content/transform/RuntimeExecutableContentTransformerTest.java @@ -74,10 +74,12 @@ public class RuntimeExecutableContentTransformerTest extends BaseAlfrescoTestCas worker.afterPropertiesSet(); TransformerDebug transformerDebug = (TransformerDebug) ctx.getBean("transformerDebug"); + TransformerConfig transformerConfig = (TransformerConfig) ctx.getBean("transformerConfig"); ProxyContentTransformer transformer = new ProxyContentTransformer(); transformer.setMimetypeService(serviceRegistry.getMimetypeService()); transformer.setTransformerDebug(transformerDebug); + transformer.setTransformerConfig(transformerConfig); transformer.setWorker(worker); this.transformer = transformer; } diff --git a/source/java/org/alfresco/repo/content/transform/RuntimeExecutableContentTransformerWorker.java b/source/java/org/alfresco/repo/content/transform/RuntimeExecutableContentTransformerWorker.java index 9537fed4b6..4dcbf7de81 100644 --- a/source/java/org/alfresco/repo/content/transform/RuntimeExecutableContentTransformerWorker.java +++ b/source/java/org/alfresco/repo/content/transform/RuntimeExecutableContentTransformerWorker.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2010 Alfresco Software Limited. + * Copyright (C) 2005-2013 Alfresco Software Limited. * * This file is part of Alfresco * @@ -169,19 +169,7 @@ public class RuntimeExecutableContentTransformerWorker extends ContentTransforme */ public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options) { - if (!available) - { - return false; - } - - if (isExplicitTransformation(sourceMimetype, targetMimetype, options)) - { - return true; - } - else - { - return false; - } + return available; } /** diff --git a/source/java/org/alfresco/repo/content/transform/StringExtractingContentTransformerTest.java b/source/java/org/alfresco/repo/content/transform/StringExtractingContentTransformerTest.java index d00b5f0932..83b9916bb8 100644 --- a/source/java/org/alfresco/repo/content/transform/StringExtractingContentTransformerTest.java +++ b/source/java/org/alfresco/repo/content/transform/StringExtractingContentTransformerTest.java @@ -68,6 +68,7 @@ public class StringExtractingContentTransformerTest extends AbstractContentTrans transformer = new StringExtractingContentTransformer(); transformer.setMimetypeService(mimetypeService); transformer.setTransformerDebug(transformerDebug); + transformer.setTransformerConfig(transformerConfig); targetWriter = new FileContentWriter(getTempFile()); targetWriter.setMimetype("text/plain"); targetWriter.setEncoding("UTF-8"); diff --git a/source/java/org/alfresco/repo/content/transform/TextMiningContentTransformerTest.java b/source/java/org/alfresco/repo/content/transform/TextMiningContentTransformerTest.java index 3005d57d43..b5a3d0dd7c 100644 --- a/source/java/org/alfresco/repo/content/transform/TextMiningContentTransformerTest.java +++ b/source/java/org/alfresco/repo/content/transform/TextMiningContentTransformerTest.java @@ -46,6 +46,7 @@ public class TextMiningContentTransformerTest extends AbstractContentTransformer transformer = new TextMiningContentTransformer(); transformer.setMimetypeService(mimetypeService); transformer.setTransformerDebug(transformerDebug); + transformer.setTransformerConfig(transformerConfig); } /** diff --git a/source/java/org/alfresco/repo/content/transform/TextToPdfContentTransformerTest.java b/source/java/org/alfresco/repo/content/transform/TextToPdfContentTransformerTest.java index dbc79e45ae..a43cbf6392 100644 --- a/source/java/org/alfresco/repo/content/transform/TextToPdfContentTransformerTest.java +++ b/source/java/org/alfresco/repo/content/transform/TextToPdfContentTransformerTest.java @@ -50,9 +50,11 @@ public class TextToPdfContentTransformerTest extends AbstractContentTransformerT transformer = new TextToPdfContentTransformer(); transformer.setMimetypeService(mimetypeService); transformer.setTransformerDebug(transformerDebug); + transformer.setTransformerConfig(transformerConfig); transformer.setStandardFont("Times-Roman"); transformer.setFontSize(20); transformer.setPageLimit(-1); + transformer.register(); } /** @@ -120,7 +122,9 @@ public class TextToPdfContentTransformerTest extends AbstractContentTransformerT private void transformTextAndCheckPageLength(int pageLimit) throws IOException { + transformer.setBeanName("transformer.test"+System.currentTimeMillis()%100000); transformer.setPageLimit(pageLimit); + transformer.register(); int pageLength = 32; int lines = (pageLength+10) * ((pageLimit > 0) ? pageLimit : 1); diff --git a/source/java/org/alfresco/repo/content/transform/TikaAutoContentTransformerTest.java b/source/java/org/alfresco/repo/content/transform/TikaAutoContentTransformerTest.java index bb31e33e31..60062fffd6 100644 --- a/source/java/org/alfresco/repo/content/transform/TikaAutoContentTransformerTest.java +++ b/source/java/org/alfresco/repo/content/transform/TikaAutoContentTransformerTest.java @@ -43,6 +43,7 @@ public class TikaAutoContentTransformerTest extends TikaPoweredContentTransforme transformer = new TikaAutoContentTransformer( config ); transformer.setMimetypeService(mimetypeService); transformer.setTransformerDebug(transformerDebug); + transformer.setTransformerConfig(transformerConfig); } /** diff --git a/source/java/org/alfresco/repo/content/transform/TransformerConfig.java b/source/java/org/alfresco/repo/content/transform/TransformerConfig.java new file mode 100644 index 0000000000..a0fe08bd12 --- /dev/null +++ b/source/java/org/alfresco/repo/content/transform/TransformerConfig.java @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2005-2012 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco 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 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Alfresco. If not, see . + */ +package org.alfresco.repo.content.transform; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + +import org.alfresco.service.cmr.repository.TransformationOptionLimits; +import org.alfresco.service.cmr.repository.TransformationOptions; + +/** + * Provides access to transformer configuration and current performance data. + * + * @author Alan Davis + */ +public interface TransformerConfig +{ + /** + * Wild card mimetype and mimetype extension. + */ + public static final String ANY = "*"; + + /** + * Prefix before the transformer name of all property names that contain transformer + * information + */ + static final String CONTENT = "content."; + + /** + * Prefix for all transformer names + */ + static final String TRANSFORMER = "transformer."; + + /** + * The combined content and transformer name prefix of for all property names that contain + * transformer information + */ + static final String PREFIX = CONTENT+TRANSFORMER; + + /** + * The 'transformer name' for system wide defaults for all transformers + */ + static final String DEFAULT_TRANSFORMER = TRANSFORMER+"default"; + + /** + * Name given to the 'SUMMARY' dummy (does not exist) transformer that gathers data + * from all root level transformations + */ + static final String SUMMARY_TRANSFORMER_NAME = "SUMMARY"; + + /** + * The separator between the transformer name and two mimetype extensions in a property name. + */ + static final String MIMETYPES_SEPARATOR = ".mimetypes."; + + /** + * The suffix to property names for supported and unsupported combinations. + */ + static final String SUPPORTED = ".supported"; + + /** + * The suffix to property names for the priority. + */ + static final String PRIORITY = ".priority"; + + /** + * The suffix to property names for the threshold count. + */ + static final String THRESHOLD_COUNT = ".thresholdCount"; + + /** + * The suffix to property names for the error time. + */ + static final String ERROR_TIME = ".errorTime"; + + /** + * The suffix to property names for the the average time. Only used in the initial setup of + * TransformerData. This is a historical property used by the 'Transformation Server' to set + * an effective priority. + */ + static final String INITIAL_TIME = ".time"; + + /** + * The suffix to property names for the the average count. Only used in the initial setup of + * TransformerData. This is a historical property used by the 'Transformation Server' to set + * an effective priority. + */ + static final String INITIAL_COUNT = ".count"; + + /** + * To support the historical concept of EXPLICIT transformers, all such transformers + * are given a {@link PRIORITY_EXPLICIT} (5). By default transformers have a default of 10. + * A value of 5 allows better transformers to be added later. + */ + public int PRIORITY_EXPLICIT = 5; + + /** + * Suffixes to property names used to define transformation limits + */ + static final Collection LIMIT_SUFFIXES = Arrays.asList(new String [] { + '.'+TransformationOptionLimits.OPT_MAX_SOURCE_SIZE_K_BYTES, + '.'+TransformationOptionLimits.OPT_TIMEOUT_MS, + '.'+TransformationOptionLimits.OPT_MAX_PAGES, + '.'+TransformationOptionLimits.OPT_READ_LIMIT_K_BYTES, + '.'+TransformationOptionLimits.OPT_READ_LIMIT_TIME_MS, + '.'+TransformationOptionLimits.OPT_PAGE_LIMIT + }); + + /** + * No suffixes to property names used to define transformer settings. + */ + public static final Collection NO_SUFFIXES = Collections.singletonList(""); + + /** + * Returns a transformer property value. + * @param name of the property. + * @return a transformer property or {@code null} if not set. + */ + String getProperty(String name); + + /** + * Sets a transformer property value. This will be stored in the database but on an MBean + * reset would be cleared. + * + * @param propertyNameAndValue + */ + void setProperty(String propertyNameAndValue); + + /** + * Returns and creates if needed the {@link TransformerStatistics} object for the combination of + * transformer, sourceMimetype and targetMimetype. When transformer is null this is the + * system wide summary object for a combination of sourceMimetype and targetMimetype. + * When both sourceMimetype and targetMimetype are null this is the transformer's summary + * object. When all three parameters are null this is the system wide summary for all + * transformers. + * @param transformer the transformer for which data is being recorded. + * @param sourceMimetype the source mimetype. + * @param targetMimetype the source mimetype. + * @return the requested {@link TransformerStatistics}. + */ + public TransformerStatistics getStatistics(ContentTransformer transformer, String sourceMimetype, String targetMimetype); + + /** + * Returns the limits defined for the combination of transformer, sourceMimetype and targetMimetype. + * When the transformer is null, this is a default value. When both sourceMimetype and targetMimetype + * are null this is a default for the specified transformer. + * @param transformer + * @param sourceMimetype + * @param targetMimetype + * @return the combined (takes into account defaults from higher levels) limits for the combination. + */ + public TransformationOptionLimits getLimits(ContentTransformer transformer, String sourceMimetype, String targetMimetype); + + /** + * Returns true if the supplied mimetype transformation pair is allowed by the list of supported + * and unsupported transformations. + * @param transformer + * @param sourceMimetype + * @param targetMimetype + * @param options not currently used + */ + public boolean isSupportedTransformation(ContentTransformer transformer, String sourceMimetype, + String targetMimetype, TransformationOptions options); + + /** + * Returns the priority of the specified transformer for the the combination of source and target mimetype. + * @param transformer + * @param sourceMimetype + * @param targetMimetype + * @return the priority. To support the historical concept of EXPLICIT transformers, all such transformers + * are given a {@link PRIORITY_EXPLICIT} (5). By default transformers have a default of 10. + */ + public int getPriority(ContentTransformer contentTransformerHelper, + String sourceMimetype, String targetMimetype); + + /** + * Returns the threshold of the transformer. It is only after this number of transformation attempts + * that the average time is used. + * @param transformer + * @param sourceMimetype + * @param targetMimetype + * @return the threshold. + */ + + public int getThresholdCount(ContentTransformer contentTransformerHelper, String sourceMimetype, + String targetMimetype); +} diff --git a/source/java/org/alfresco/repo/content/transform/TransformerConfigImpl.java b/source/java/org/alfresco/repo/content/transform/TransformerConfigImpl.java new file mode 100644 index 0000000000..d65edc34cc --- /dev/null +++ b/source/java/org/alfresco/repo/content/transform/TransformerConfigImpl.java @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2005-2012 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco 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 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Alfresco. If not, see . + */ +package org.alfresco.repo.content.transform; + +import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory; +import org.alfresco.service.cmr.repository.MimetypeService; +import org.alfresco.service.cmr.repository.TransformationOptionLimits; +import org.alfresco.service.cmr.repository.TransformationOptions; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.context.ApplicationEvent; +import org.springframework.extensions.surf.util.AbstractLifecycleBean; + +/** + * Provides access to transformer configuration and current performance data. + * + * @author Alan Davis + */ +public class TransformerConfigImpl extends AbstractLifecycleBean implements TransformerConfig +{ + /** The logger. */ + private static Log logger = LogFactory.getLog(TransformerConfigImpl.class); + + private MimetypeService mimetypeService; + + // Holds statistics about each transformer, sourceMimeType and targetMimetype combination. + // A null transformer is the system wide value. Null sourceMimeType and targetMimetype values are + // transformer wide summaries. + private TransformerConfigStatistics statistics; + + // Transformer limits. + private TransformerConfigLimits limits; + + // Supported and unsupported transformations. + private TransformerConfigSupported supported; + + // Priorities + private TransformerConfigProperty priorities; + + // Threshold counts - Initially there will only be the system wide value, but + // having this structure provides flexibility. + private TransformerConfigProperty thresholdCounts; + + // Times to be recorded if there is an error - Initially there will only be the system wide value, but + // having this structure provides flexibility. + private TransformerConfigProperty errorTimes; + + // For backward compatibility where priority could not be set, with AMPs that need to have their + // transformer used rather than an inbuilt one. Achieved by making the inbuilt transformers look + // poor. Generally contains no entries, other than the system wide 0 values. + private TransformerConfigProperty initialAverageTimes; + private TransformerConfigProperty initialCounts; + + // Needed to read properties. + private ChildApplicationContextFactory subsystemFactory; + + /** + * Sets of the mimetype service. + * + * @param mimetypeService + */ + public void setMimetypeService(MimetypeService mimetypeService) + { + this.mimetypeService = mimetypeService; + } + + /** + * Called by spring after bean is initialised. + */ + public void initialise() + { + statistics= new TransformerConfigStatistics(this, mimetypeService); + limits = new TransformerConfigLimits(getSubsystem(), mimetypeService); + supported = new TransformerConfigSupported(getSubsystem(), mimetypeService); + priorities = new TransformerConfigProperty(getSubsystem(), mimetypeService, PRIORITY); + thresholdCounts = new TransformerConfigProperty(getSubsystem(), mimetypeService, THRESHOLD_COUNT); + errorTimes = new TransformerConfigProperty(getSubsystem(), mimetypeService, ERROR_TIME); + initialAverageTimes = new TransformerConfigProperty(getSubsystem(), mimetypeService, INITIAL_TIME); + initialCounts = new TransformerConfigProperty(getSubsystem(), mimetypeService, INITIAL_COUNT); + } + + /** + * Returns the 'transformers' subsystem which among other things holds transformer properties. + */ + private synchronized ChildApplicationContextFactory getSubsystem() + { + if (subsystemFactory == null) + { + subsystemFactory = getApplicationContext().getBean("Transformers", ChildApplicationContextFactory.class); + } + return subsystemFactory; + } + + @Override + protected void onBootstrap(ApplicationEvent event) + { + } + + @Override + protected void onShutdown(ApplicationEvent event) + { + } + + /** + * {@inheritDoc} + */ + @Override + public String getProperty(String name) + { + return getSubsystem().getProperty(name); + } + + /** + * {@inheritDoc} + */ + @Override + public void setProperty(String propertyNameAndValue) + { + int i = propertyNameAndValue.indexOf('='); + String name = i != -1 ? propertyNameAndValue.substring(0, i) : propertyNameAndValue; + String value = i != -1 ? propertyNameAndValue.substring(i+1) : ""; + getSubsystem().setProperty(name, value); + } + + /** + * {@inheritDoc} + */ + @Override + public TransformerStatistics getStatistics(ContentTransformer transformer, String sourceMimetype, String targetMimetype) + { + return statistics.getStatistics(transformer, sourceMimetype, targetMimetype); + } + + /** + * {@inheritDoc} + */ + @Override + public TransformationOptionLimits getLimits(ContentTransformer transformer, String sourceMimetype, + String targetMimetype) + { + return limits.getLimits(transformer, sourceMimetype, targetMimetype); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isSupportedTransformation(ContentTransformer transformer, String sourceMimetype, + String targetMimetype, TransformationOptions options) + { + return supported.isSupportedTransformation(transformer, sourceMimetype, targetMimetype, options); + } + + /** + * {@inheritDoc} + */ + @Override + public int getPriority(ContentTransformer transformer, String sourceMimetype, String targetMimetype) + { + return priorities.getInt(transformer, sourceMimetype, targetMimetype); + } + + /** + * {@inheritDoc} + */ + @Override + public int getThresholdCount(ContentTransformer transformer, String sourceMimetype, String targetMimetype) + { + return thresholdCounts.getInt(transformer, sourceMimetype, targetMimetype); + } + + /** + * Gets the time to be recorded if there is an error. + */ + long getErrorTime(ContentTransformer transformer, String sourceMimetype, String targetMimetype) + { + return errorTimes.getLong(transformer, sourceMimetype, targetMimetype); + } + + /** + * Gets the initial average time to be set for a transformer. Used historically to set the priority of transformers in AMPs. + * The initial count value may also obtained via {@link #getInitialCount(ContentTransformer, String, String)}. + */ + long getInitialAverageTime(ContentTransformer transformer, String sourceMimetype, String targetMimetype) + { + return initialAverageTimes.getLong(transformer, sourceMimetype, targetMimetype); + } + + /** + * Gets the initial transformer count to be set for a transformer. Used historically to set the priority of transformers in AMPs. + * Only called if {@link #getInitialAverageTime(ContentTransformer, String, String)} returns a value larger than 0. + */ + int getInitialCount(ContentTransformer transformer, String sourceMimetype, String targetMimetype) + { + return initialCounts.getInt(transformer, sourceMimetype, targetMimetype); + } +} diff --git a/source/java/org/alfresco/repo/content/transform/TransformerConfigLimits.java b/source/java/org/alfresco/repo/content/transform/TransformerConfigLimits.java new file mode 100644 index 0000000000..917127a4a1 --- /dev/null +++ b/source/java/org/alfresco/repo/content/transform/TransformerConfigLimits.java @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2005-2013 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco 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 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Alfresco. If not, see . + */ +package org.alfresco.repo.content.transform; + +import static org.alfresco.repo.content.transform.TransformerConfig.ANY; +import static org.alfresco.repo.content.transform.TransformerConfig.CONTENT; +import static org.alfresco.repo.content.transform.TransformerConfig.DEFAULT_TRANSFORMER; +import static org.alfresco.repo.content.transform.TransformerConfig.LIMIT_SUFFIXES; +import static org.alfresco.repo.content.transform.TransformerConfig.MIMETYPES_SEPARATOR; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory; +import org.alfresco.service.cmr.repository.MimetypeService; +import org.alfresco.service.cmr.repository.TransformationOptionLimits; +import org.alfresco.util.Triple; + +/** + * Provides access to transformer limits defined via properties. + * + * @author Alan Davis + */ +public class TransformerConfigLimits extends TransformerPropertyNameExtractor +{ + // Holds configured (entries only exist if configured rather than for all possible combinations) + // limits for for transformer, sourceMimeType and targetMimetype combination. + // A null transformer is the system wide value. SourceMimeType and targetMimetype may be 'ANY' + // values to act as wild cards. + private Map> limits; + + public TransformerConfigLimits(ChildApplicationContextFactory subsystem, MimetypeService mimetypeService) + { + setLimits(subsystem, mimetypeService); + } + + /** + * Sets the transformer limits created from system properties. + */ + private void setLimits(ChildApplicationContextFactory subsystem, MimetypeService mimetypeService) + { + limits = new HashMap>(); + + // Gets all the transformer, source and target combinations in properties that define limits. + Set> transformerNamesAndExt = + getTransformerNamesAndExt(MIMETYPES_SEPARATOR, LIMIT_SUFFIXES, true, subsystem, mimetypeService); + + // Add the system wide default just in case it is not included, as we always need this one + transformerNamesAndExt.add(new Triple(DEFAULT_TRANSFORMER, ANY, ANY)); + + // Populate the transformer limits + for (Triple triple: transformerNamesAndExt) + { + String transformerName = triple.getFirst(); + String sourceExt = triple.getSecond(); + String targetExt = triple.getThird(); + String sourceMimetype = ANY.equals(sourceExt) ? ANY : mimetypeService.getMimetype(sourceExt); + String targetMimetype = ANY.equals(targetExt) ? ANY : mimetypeService.getMimetype(targetExt); + + TransformationOptionLimits limits = newTransformationOptionLimits(transformerName, sourceExt, targetExt, subsystem); + + DoubleMap mimetypeLimits = + this.limits.get(transformerName); + if (mimetypeLimits == null) + { + mimetypeLimits = new DoubleMap(ANY, ANY); + this.limits.put(transformerName, mimetypeLimits); + } + mimetypeLimits.put(sourceMimetype, targetMimetype, limits); + } + } + + /** + * Returns a TransformationOptionLimits object using property values. + * @param transformerName + * @param sourceExt is null for overall transformer options rather than for a specific mimetype pair + * @param targetExt is null for overall transformer options rather than for a specific mimetype pair + * @return a TransformationOptionLimits object or null if not created + */ + private TransformationOptionLimits newTransformationOptionLimits(String transformerName, + String sourceExt, String targetExt, ChildApplicationContextFactory subsystem) + { + TransformationOptionLimits limits = new TransformationOptionLimits(); + + // The overall values can be defined in two ways + if (ANY.equals(sourceExt) && ANY.equals(targetExt)) + { + setTransformationOptionsFromProperties(limits, transformerName, null, null, subsystem); + } + setTransformationOptionsFromProperties(limits, transformerName, sourceExt, targetExt, subsystem); + + return limits; + } + + private void setTransformationOptionsFromProperties(TransformationOptionLimits limits, + String transformerName, String sourceExt, String targetExt, ChildApplicationContextFactory subsystem) + { + String propertyNameRoot = CONTENT+transformerName+ + (sourceExt == null ? "" : MIMETYPES_SEPARATOR+sourceExt+'.'+targetExt); + int i = 0; + for (String suffix: LIMIT_SUFFIXES) + { + String value = subsystem.getProperty(propertyNameRoot+suffix); + if (value != null) + { + long l = Long.parseLong(value); + switch (i) + { + case 0: + limits.setMaxSourceSizeKBytes(l); + break; + case 1: + limits.setTimeoutMs(l); + break; + case 2: + limits.setMaxPages((int)l); + break; + case 3: + limits.setReadLimitKBytes(l); + break; + case 4: + limits.setReadLimitTimeMs(l); + break; + case 5: + limits.setPageLimit((int)l); + break; + } + } + i++; + } + } + + /** + * See {@link TransformerConfig#getLimits(ContentTransformer, String, String)}. + */ + public TransformationOptionLimits getLimits(ContentTransformer transformer, String sourceMimetype, + String targetMimetype) + { + if (sourceMimetype == null) + { + sourceMimetype = ANY; + } + + if (targetMimetype == null) + { + targetMimetype = ANY; + } + + String name = (transformer == null) ? DEFAULT_TRANSFORMER : transformer.getName(); + + DoubleMap transformerLimits = limits.get(name); + + TransformationOptionLimits limits = (transformerLimits == null) ? null : transformerLimits.get(sourceMimetype, targetMimetype); + + // Individual transformer limits might not exist. + TransformationOptionLimits transformerWideLimits = (transformerLimits == null) ? null : transformerLimits.get(ANY, ANY); + limits = (limits == null) ? transformerWideLimits : transformerWideLimits == null ? limits : transformerWideLimits.combine(limits); + + // If a non recursive call + if (transformer != null) + { + // System wide 'default' limits should exist. + TransformationOptionLimits systemWideLimits = getLimits(null, sourceMimetype, targetMimetype); + limits = (limits == null) ? systemWideLimits : systemWideLimits.combine(limits); + } + + return limits; + } +} diff --git a/source/java/org/alfresco/repo/content/transform/TransformerConfigProperty.java b/source/java/org/alfresco/repo/content/transform/TransformerConfigProperty.java new file mode 100644 index 0000000000..cf5c46b079 --- /dev/null +++ b/source/java/org/alfresco/repo/content/transform/TransformerConfigProperty.java @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2005-2013 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco 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 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Alfresco. If not, see . + */ +package org.alfresco.repo.content.transform; + +import static org.alfresco.repo.content.transform.TransformerConfig.ANY; +import static org.alfresco.repo.content.transform.TransformerConfig.CONTENT; +import static org.alfresco.repo.content.transform.TransformerConfig.DEFAULT_TRANSFORMER; +import static org.alfresco.repo.content.transform.TransformerConfig.MIMETYPES_SEPARATOR; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory; +import org.alfresco.service.cmr.repository.MimetypeService; +import org.alfresco.util.Triple; + +/** + * Provides access to single transformer configuration property depending on the + * transformer and source and target mimetypes, falling back to defaults. + * + * @author Alan Davis + */ +public class TransformerConfigProperty extends TransformerPropertyNameExtractor +{ + private Map> values; + + public TransformerConfigProperty(ChildApplicationContextFactory subsystem, + MimetypeService mimetypeService, String propertySuffix) + { + setValues(subsystem, mimetypeService, propertySuffix); + } + + /** + * Sets the transformer values created from system properties. + */ + private void setValues(ChildApplicationContextFactory subsystem, MimetypeService mimetypeService, String propertySuffix) + { + values = new HashMap>(); + + // Gets all the transformer, source and target combinations in properties that define + // this value. + Set> transformerNamesAndMimetypes = + getTransformerNamesAndExt(MIMETYPES_SEPARATOR, Collections.singletonList(propertySuffix), true, subsystem, mimetypeService); + + // Add the system wide default just in case it is not included, as we always need this one + transformerNamesAndMimetypes.add(new Triple(DEFAULT_TRANSFORMER, ANY, ANY)); + + // Populate the transformer values + for (Triple triple: transformerNamesAndMimetypes) + { + String transformerName = triple.getFirst(); + String sourceExt = triple.getSecond(); + String targetExt = triple.getThird(); + String sourceMimetype = ANY.equals(sourceExt) ? ANY : mimetypeService.getMimetype(sourceExt); + String targetMimetype = ANY.equals(targetExt) ? ANY : mimetypeService.getMimetype(targetExt); + + String value = newTransformerValue(transformerName, sourceExt, targetExt, subsystem, propertySuffix); + + DoubleMap mimetypeLimits = this.values.get(transformerName); + if (mimetypeLimits == null) + { + mimetypeLimits = new DoubleMap(ANY, ANY); + this.values.put(transformerName, mimetypeLimits); + } + mimetypeLimits.put(sourceMimetype, targetMimetype, value); + } + } + + /** + * Returns a String object using property values. + * @param transformerName + * @param sourceExt is null for overall transformer options rather than for a specific mimetype pair + * @param targetExt is null for overall transformer options rather than for a specific mimetype pair + * @return a String object or null if not created + */ + private String newTransformerValue(String transformerName, String sourceExt, String targetExt, + ChildApplicationContextFactory subsystem, String propertySuffix) + { + String value = getValueFromProperties(transformerName, sourceExt, targetExt, subsystem, propertySuffix); + + // The overall values can be defined in another way + if (value == null && ANY.equals(sourceExt) && ANY.equals(targetExt)) + { + value = getValueFromProperties(transformerName, null, null, subsystem, propertySuffix); + } + + return value; + } + + private String getValueFromProperties(String transformerName, String sourceExt, String targetExt, + ChildApplicationContextFactory subsystem, String propertySuffix) + { + String propertyName = CONTENT+transformerName+ + (sourceExt == null ? "" : MIMETYPES_SEPARATOR+sourceExt+'.'+targetExt)+ + propertySuffix; + String value = subsystem.getProperty(propertyName); + return value; + } + + private String getString(ContentTransformer transformer, String sourceMimetype, + String targetMimetype) + { + if (sourceMimetype == null) + { + sourceMimetype = ANY; + } + + if (targetMimetype == null) + { + targetMimetype = ANY; + } + + String name = (transformer == null) ? DEFAULT_TRANSFORMER : transformer.getName(); + + DoubleMap mimetypeLimits = values.get(name); + + String value = (mimetypeLimits == null) ? null : mimetypeLimits.get(sourceMimetype, targetMimetype); + + if (value == null && transformer != null) + { + // System wide 'default' limits should exist, but individual transformer values might not. + value = getString(null, sourceMimetype, targetMimetype); + } + + return value; + } + + public long getLong(ContentTransformer transformer, String sourceMimetype, String targetMimetype) + { + return Long.parseLong(getString(transformer, sourceMimetype, targetMimetype)); + } + + public int getInt(ContentTransformer transformer, String sourceMimetype, String targetMimetype) + { + return Integer.parseInt(getString(transformer, sourceMimetype, targetMimetype)); + } +} diff --git a/source/java/org/alfresco/repo/content/transform/TransformerConfigStatistics.java b/source/java/org/alfresco/repo/content/transform/TransformerConfigStatistics.java new file mode 100644 index 0000000000..434428f271 --- /dev/null +++ b/source/java/org/alfresco/repo/content/transform/TransformerConfigStatistics.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2005-2013 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco 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 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Alfresco. If not, see . + */ +package org.alfresco.repo.content.transform; + +import static org.alfresco.repo.content.transform.TransformerConfig.ANY; +import static org.alfresco.repo.content.transform.TransformerConfig.SUMMARY_TRANSFORMER_NAME; + +import java.util.HashMap; +import java.util.Map; + +import org.alfresco.service.cmr.repository.MimetypeService; + +/** + * Provides a place to store and access statistics about transformers, source and target mimetypes combinations. + * It also provides summaries for transformers as a whole and the system as a whole. + * + * @author Alan Davis + */ +public class TransformerConfigStatistics +{ + private TransformerConfigImpl transformerConfigImpl; + private MimetypeService mimetypeService; + + // Holds statistics about each transformer, sourceMimeType and targetMimetype combination. + // A null transformer is the system wide value. Null sourceMimeType and targetMimetype values are + // transformer wide summaries. + private Map> statistics = + new HashMap>(); + + public TransformerConfigStatistics(TransformerConfigImpl transformerConfigImpl, + MimetypeService mimetypeService) + { + this.transformerConfigImpl = transformerConfigImpl; + this.mimetypeService = mimetypeService; + } + + public TransformerStatistics getStatistics(ContentTransformer transformer, String sourceMimetype, String targetMimetype) + { + if (sourceMimetype == null) + { + sourceMimetype = ANY; + } + + if (targetMimetype == null) + { + targetMimetype = ANY; + } + + TransformerStatistics transformerStatistics; + + String name = (transformer == null) ? SUMMARY_TRANSFORMER_NAME : transformer.getName(); + DoubleMap mimetypeStatistics = statistics.get(name); + + if (mimetypeStatistics == null) + { + // Create the summary for the transformer as a whole + mimetypeStatistics = new DoubleMap(ANY, ANY); + statistics.put(name, mimetypeStatistics); + transformerStatistics = newTransformerStatistics(transformer, ANY, ANY, null); + mimetypeStatistics.put(ANY, ANY, transformerStatistics); + } + + if (ANY.equals(sourceMimetype) && ANY.equals(targetMimetype)) + { + transformerStatistics = mimetypeStatistics.get(ANY, ANY); + } + else + { + // Not looking for the summary, so will have to create if not found or the summary is returned + transformerStatistics = mimetypeStatistics.get(sourceMimetype, targetMimetype); + if (transformerStatistics == null || transformerStatistics.isSummary()) + { + // Create individual mimetype to mimetype transformation by this transformer + transformerStatistics = newTransformerStatistics(transformer, sourceMimetype, targetMimetype, mimetypeStatistics.get(ANY, ANY)); + mimetypeStatistics.put(sourceMimetype, targetMimetype, transformerStatistics); + } + } + + return transformerStatistics; + } + + private TransformerStatistics newTransformerStatistics(ContentTransformer transformer, + String sourceMimetype, String targetMimetype, TransformerStatistics parent) + { + long initialAverageTime = transformerConfigImpl.getInitialAverageTime(transformer, sourceMimetype, targetMimetype); + long initialCount = initialAverageTime <= 0 + ? 0 + : transformerConfigImpl.getInitialCount(transformer, sourceMimetype, targetMimetype); + long errorTime = transformerConfigImpl.getErrorTime(transformer, sourceMimetype, targetMimetype); + + TransformerStatistics transformerStatistics = new TransformerStatisticsImpl(mimetypeService, sourceMimetype, targetMimetype, + transformer, parent, errorTime, initialAverageTime, initialCount); + + return transformerStatistics; + } + +} diff --git a/source/java/org/alfresco/repo/content/transform/TransformerConfigSupported.java b/source/java/org/alfresco/repo/content/transform/TransformerConfigSupported.java new file mode 100644 index 0000000000..7de77fc9e3 --- /dev/null +++ b/source/java/org/alfresco/repo/content/transform/TransformerConfigSupported.java @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2005-2013 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco 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 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Alfresco. If not, see . + */ +package org.alfresco.repo.content.transform; + +import static org.alfresco.repo.content.transform.TransformerConfig.ANY; +import static org.alfresco.repo.content.transform.TransformerConfig.CONTENT; +import static org.alfresco.repo.content.transform.TransformerConfig.MIMETYPES_SEPARATOR; +import static org.alfresco.repo.content.transform.TransformerConfig.SUPPORTED; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory; +import org.alfresco.service.cmr.repository.MimetypeService; +import org.alfresco.service.cmr.repository.TransformationOptions; +import org.alfresco.util.Triple; + +/** + * Provides access to the lists of supported and unsupported mimetype transformations + * defined via properties for all transformers. + * + * @author Alan Davis + */ +public class TransformerConfigSupported extends TransformerPropertyNameExtractor +{ + // Holds configured (entries only exist if configured rather than for all possible combinations) + // of supported and unsupported mimetypes transformations for a transformer. + // SourceMimetype and targetMimetype may be 'ANY' values to act as wild cards. + private Map supported; + + public TransformerConfigSupported(ChildApplicationContextFactory subsystem, MimetypeService mimetypeService) + { + setSupported(subsystem, mimetypeService); + } + + /** + * Sets the supported/unsupported mimetype transformations created from system properties. + */ + private void setSupported(ChildApplicationContextFactory subsystem, MimetypeService mimetypeService) + { + supported = new HashMap(); + + // Gets all the supported and unsupported transformer, source and target combinations + Set> transformerNamesAndMimetypes = + getTransformerNamesAndExt(MIMETYPES_SEPARATOR, Collections.singletonList(SUPPORTED), false, subsystem, mimetypeService); + + + + + // Populate the transformer values + for (Triple triple: transformerNamesAndMimetypes) + { + String transformerName = triple.getFirst(); + String sourceExt = triple.getSecond(); + String targetExt = triple.getThird(); + String sourceMimetype = ANY.equals(sourceExt) ? ANY : mimetypeService.getMimetype(sourceExt); + String targetMimetype = ANY.equals(targetExt) ? ANY : mimetypeService.getMimetype(targetExt); + + SupportedAndUnsupportedTransformations supportedBytransformer = this.supported.get(transformerName); + + if (supportedBytransformer == null) + { + supportedBytransformer = new SupportedAndUnsupportedTransformations(); + this.supported.put(transformerName, supportedBytransformer); + } + boolean supported = getValueFromProperties(transformerName, sourceExt, targetExt, subsystem, SUPPORTED); + supportedBytransformer.put(sourceMimetype, targetMimetype, supported); + } + } + + private boolean getValueFromProperties(String transformerName, String sourceExt, String targetExt, + ChildApplicationContextFactory subsystem, String propertySuffix) + { + String propertyName = CONTENT+transformerName+ + (sourceExt == null ? "" : MIMETYPES_SEPARATOR+sourceExt+'.'+targetExt)+ + propertySuffix; + String value = subsystem.getProperty(propertyName); + return value == null || value.equalsIgnoreCase("true"); + } + + /** + * See {@link TransformerConfig#isSupportedTransformation(ContentTransformer, String, String, TransformationOptions)}. + */ + public boolean isSupportedTransformation(ContentTransformer transformer, String sourceMimetype, + String targetMimetype, TransformationOptions options) + { + if (sourceMimetype == null) + { + sourceMimetype = ANY; + } + + if (targetMimetype == null) + { + targetMimetype = ANY; + } + + boolean isSupported = true; + String name = transformer.getName(); + SupportedAndUnsupportedTransformations supportedBytransformer = supported.get(name); + if (supportedBytransformer != null) + { + isSupported = supportedBytransformer.isSupported(sourceMimetype, targetMimetype); + } + return isSupported; + } + + // Class contains both supported and unsupported combinations to avoid having to + // add in an extra ANY to ANY combination which could be true or false. Having an + // extra combination might reduce understandability. + private class SupportedAndUnsupportedTransformations + { + DoubleMap supportedTransformations; + DoubleMap unsupportedTransformations; + + boolean isSupported(String sourceMimetype, String targetMimetype) + { + boolean isSupported = true; + if (supportedTransformations != null) + { + Boolean sup = supportedTransformations.get(sourceMimetype, targetMimetype); + isSupported = sup != null; + } + if (isSupported && unsupportedTransformations != null) + { + Boolean sup = unsupportedTransformations.get(sourceMimetype, targetMimetype); + isSupported = sup == null; + } + return isSupported; + } + + public void put(String sourceMimetype, String targetMimetype, boolean supported) + { + if (supported) + { + if (supportedTransformations == null) + { + supportedTransformations = new DoubleMap(ANY, ANY); + } + supportedTransformations.put(sourceMimetype, targetMimetype, supported); + } + else + { + if (unsupportedTransformations == null) + { + unsupportedTransformations = new DoubleMap(ANY, ANY); + } + unsupportedTransformations.put(sourceMimetype, targetMimetype, supported); + } + } + } +} diff --git a/source/java/org/alfresco/repo/content/transform/TransformerDebug.java b/source/java/org/alfresco/repo/content/transform/TransformerDebug.java index bbad7a87b4..2af69f6aae 100644 --- a/source/java/org/alfresco/repo/content/transform/TransformerDebug.java +++ b/source/java/org/alfresco/repo/content/transform/TransformerDebug.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2012 Alfresco Software Limited. + * Copyright (C) 2005-2013 Alfresco Software Limited. * * This file is part of Alfresco * @@ -118,6 +118,7 @@ public class TransformerDebug private final long start; private Call callType; + private Frame parent; private int childId; private Set unavailableTransformers; private String failureReason; @@ -127,7 +128,8 @@ public class TransformerDebug private Frame(Frame parent, String transformerName, String fromUrl, String sourceMimetype, String targetMimetype, long sourceSize, TransformationOptions options, Call pushCall, boolean origDebugOutput) { - this.id = parent == null ? -1 : ++parent.childId; + this.id = -1; + this.parent = parent; this.fromUrl = fromUrl; this.transformerName = transformerName; this.sourceMimetype = sourceMimetype; @@ -143,8 +145,8 @@ public class TransformerDebug { if (id == -1) { - id = uniqueId.getAndIncrement(); - } + id = parent == null ? uniqueId.getAndIncrement() : ++parent.childId; + } return id; } @@ -223,14 +225,16 @@ public class TransformerDebug private final NodeService nodeService; private final MimetypeService mimetypeService; + private final TransformerConfig transformerConfig; /** * Constructor */ - public TransformerDebug(NodeService nodeService, MimetypeService mimetypeService) + public TransformerDebug(NodeService nodeService, MimetypeService mimetypeService, TransformerConfig transformerConfig) { this.nodeService = nodeService; this.mimetypeService = mimetypeService; + this.transformerConfig = transformerConfig; } /** @@ -373,8 +377,10 @@ public class TransformerDebug long maxSourceSizeKBytes = trans.getMaxSourceSizeKBytes(frame.sourceMimetype, frame.targetMimetype, frame.options); String size = maxSourceSizeKBytes > 0 ? "< "+fileSize(maxSourceSizeKBytes*1024) : ""; int padSize = 10 - size.length(); - log((c == 'a' ? "**" : " ") + (c++) + ") " + name + spaces(padName) + - size + spaces(padSize) + ms(trans.getTransformationTime())); + String priority = Integer.toString(transformerConfig.getPriority(trans, frame.sourceMimetype, frame.targetMimetype)); + priority = spaces(2-priority.length())+priority; + log((c == 'a' ? "**" : " ") + (c++) + ") " + priority + ' ' + name + spaces(padName) + + size + spaces(padSize) + ms(trans.getTransformationTime(frame.sourceMimetype, frame.targetMimetype))); } if (frame.unavailableTransformers != null) { @@ -382,7 +388,7 @@ public class TransformerDebug { int pad = longestNameLength - unavailable.name.length(); String reason = "> "+fileSize(unavailable.maxSourceSizeKBytes*1024); - log("--" + (c++) + ") " + unavailable.name + spaces(pad+1) + reason, unavailable.debug); + log("--" + (c++) + ") " + unavailable.name + spaces(pad+1) + reason, unavailable.debug); } } } @@ -390,7 +396,7 @@ public class TransformerDebug public void inactiveTransformer(ContentTransformer transformer) { - log(getName(transformer)+' '+ms(transformer.getTransformationTime())+" INACTIVE"); + log(getName(transformer)+' '+ms(transformer.getTransformationTime(null, null))+" INACTIVE"); } public void activeTransformer(int mimetypePairCount, ContentTransformer transformer, String sourceMimetype, @@ -398,7 +404,7 @@ public class TransformerDebug { if (firstMimetypePair) { - log(getName(transformer)+' '+ms(transformer.getTransformationTime())); + log(getName(transformer)+' '+ms(transformer.getTransformationTime(sourceMimetype, targetMimetype))); } String i = Integer.toString(mimetypePairCount); log(spaces(5-i.length())+mimetypePairCount+") "+getMimetypeExt(sourceMimetype)+getMimetypeExt(targetMimetype)+ @@ -416,7 +422,7 @@ public class TransformerDebug : spaces(10); char c = (char)('a'+transformerCount); log(mimetypes+ - " "+c+") "+getName(transformer)+' '+ms(transformer.getTransformationTime())+ + " "+c+") "+getName(transformer)+' '+ms(transformer.getTransformationTime(sourceMimetype, targetMimetype))+ ' '+fileSize((maxSourceSizeKBytes > 0) ? maxSourceSizeKBytes*1024 : maxSourceSizeKBytes)+ (maxSourceSizeKBytes == 0 || (explicit != null && !explicit) ? " disabled" : "")+ (explicit == null ? "" : explicit ? " EXPLICIT" : " not explicit")); @@ -593,8 +599,8 @@ public class TransformerDebug (fileName == null ? "" : fileName) + (sourceSize >= 0 ? ' '+fileSize(sourceSize) : "") + (transformerName == null ? "" : ' '+transformerName) + - (failureReason == null ? "" : ' '+failureReason) + - ' '+ms; + ' '+ms + + (failureReason == null ? "" : '\n'+failureReason.trim()); info.log(message, debug); } diff --git a/source/java/org/alfresco/repo/content/transform/TransformerPropertyNameExtractor.java b/source/java/org/alfresco/repo/content/transform/TransformerPropertyNameExtractor.java new file mode 100644 index 0000000000..b937b1ab91 --- /dev/null +++ b/source/java/org/alfresco/repo/content/transform/TransformerPropertyNameExtractor.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2005-2013 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco 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 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Alfresco. If not, see . + */ +package org.alfresco.repo.content.transform; + +import static org.alfresco.repo.content.transform.TransformerConfig.ANY; +import static org.alfresco.repo.content.transform.TransformerConfig.CONTENT; +import static org.alfresco.repo.content.transform.TransformerConfig.PREFIX; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory; +import org.alfresco.service.cmr.repository.MimetypeService; +import org.alfresco.util.Triple; + +/** + * Provides access to transformer property names and values. + * + * @author Alan Davis + */ +public abstract class TransformerPropertyNameExtractor +{ + /** + * Returns a set of transformer names, source extensions and target mimetype extensions + * from property names that defined transformation limits. + * @param separator after the transformer name and the source mimetype extension. + * Must start and end in a '.'. + * @param suffixes possible endings to the property names after the target mimetype extension. + * Must start with a '.' if there is a suffix. + * @param includeSummary if true will also look for property names without the separator, + * source mimetype and target mimetype. + * @param subsystem that provides the properties + * @param mimetypeService + */ + protected Set> getTransformerNamesAndExt(String separator, Collection suffixes, boolean includeSummary, + ChildApplicationContextFactory subsystem, MimetypeService mimetypeService) + { + Set> transformerNamesAndExtensions = + new HashSet>(); + + for (String propertyName: subsystem.getPropertyNames()) + { + if (propertyName.startsWith(PREFIX)) + { + for (String suffix: suffixes) + { + if (propertyName.endsWith(suffix)) + { + String name = propertyName.substring(CONTENT.length(), propertyName.length()-suffix.length()); + int i = name.lastIndexOf(separator); + if (i != -1) + { + String[] ext = name.substring(i+separator.length()).split("\\."); + if (ext.length == 2) + { + name = name.substring(0, i); + transformerNamesAndExtensions.add( + new Triple(name, ext[0], ext[1])); + break; + } + } + else if (includeSummary) + { + transformerNamesAndExtensions.add(new Triple(name, ANY, ANY)); + break; + } + } + } + } + } + + return transformerNamesAndExtensions; + } +} \ No newline at end of file diff --git a/source/java/org/alfresco/repo/content/transform/TransformerSelector.java b/source/java/org/alfresco/repo/content/transform/TransformerSelector.java index a0279ff75e..f5c97882cf 100644 --- a/source/java/org/alfresco/repo/content/transform/TransformerSelector.java +++ b/source/java/org/alfresco/repo/content/transform/TransformerSelector.java @@ -33,15 +33,12 @@ public interface TransformerSelector /** * Returns a sorted list of transformers that identifies the order in which transformers * should be tried. - * @param transformers an unordered list of all transformers. This - * list may be modified. * @param sourceMimetype * @param sourceSize * @param targetMimetype * @param options transformation options * @return a sorted list of transformers, with the best one first. */ - List selectTransformers(List transformers, - String sourceMimetype, long sourceSize, String targetMimetype, - TransformationOptions options); + List selectTransformers(String sourceMimetype, long sourceSize, + String targetMimetype, TransformationOptions options); } diff --git a/source/java/org/alfresco/repo/content/transform/TransformerSelectorImpl.java b/source/java/org/alfresco/repo/content/transform/TransformerSelectorImpl.java index 3a9d8a36b8..86f714b8be 100644 --- a/source/java/org/alfresco/repo/content/transform/TransformerSelectorImpl.java +++ b/source/java/org/alfresco/repo/content/transform/TransformerSelectorImpl.java @@ -28,94 +28,127 @@ import java.util.Map; import org.alfresco.service.cmr.repository.TransformationOptions; /** - * Implementation of a transformer selector that matches the code that was in place - * before a selector was introduced. It is expected that this code will be replaced. + * Default transformer selector implementation, which sorts by priority and then + * by average transform time. The transform time is only used once a threshold + * (number of transforms) has been reached. This average is maintained for each + * source target mimetype pair.

+ * + * Prior to the introduction of this class the transformation time was only kept + * for each transformer. There was no threshold and there was a concept of + * 'Explicit' transformers, which would cause all other transformers to be discarded. + * It is still possible to disable transformers by giving adding unsupported mappings + * as has been done for transformers that would not have been used in the past as + * there existed one or more 'explicit' transformers (a concept not used by this + * TransformerSelector). By default a transformer has a priority of {@code 10}. + * Old 'Explicit' transformers have been given a priority of {@code 5}. * * @author Alan Davis */ public class TransformerSelectorImpl implements TransformerSelector { + private TransformerConfig transformerConfig; + private ContentTransformerRegistry contentTransformerRegistry; + + public void setTransformerConfig(TransformerConfig transformerConfig) + { + this.transformerConfig = transformerConfig; + } + + public void setContentTransformerRegistry(ContentTransformerRegistry contentTransformerRegistry) + { + this.contentTransformerRegistry = contentTransformerRegistry; + } @Override - public List selectTransformers(List transformers, - String sourceMimetype, long sourceSize, String targetMimetype, - TransformationOptions options) + public List selectTransformers(String sourceMimetype, long sourceSize, + String targetMimetype, TransformationOptions options) { - transformers = findTransformers(transformers, sourceMimetype, sourceSize, targetMimetype, options); - transformers = discardNonExplicitTransformers(transformers, sourceMimetype, sourceSize, targetMimetype, options); - transformers = sortTransformers(transformers, sourceMimetype, sourceSize, targetMimetype, options); - return transformers; + // TODO cache results for reuse. This was a heavy operation in the past and still is. + + List transformers = contentTransformerRegistry.getTransformers(); + List possibleTransformers = findTransformers(transformers, sourceMimetype, sourceSize, targetMimetype, options); + return sortTransformers(possibleTransformers); } /** - * Reduces the list of transformers down to only those capable of doing the transformation. + * Returns the list of possible transformers for the transformation. */ - private List findTransformers(List allTransformers, String sourceMimetype, + private List findTransformers(List allTransformers, String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options) { - List transformers = new ArrayList(2); - + List transformers = new ArrayList(8); for (ContentTransformer transformer : allTransformers) { - if (transformer.isTransformable(sourceMimetype, sourceSize, targetMimetype, options) == true) + int priority = transformerConfig.getPriority(transformer, sourceMimetype, targetMimetype); + if (priority > 0 && + transformer.isTransformable(sourceMimetype, sourceSize, targetMimetype, options) == true) + { - transformers.add(transformer); + transformers.add(new TransformerSortData(transformer, sourceMimetype, targetMimetype, priority)); } } return transformers; } /** - * Discards non explicit transformers if there are any explicit ones. + * Returns a sorted list of transformers by priority and then average time (ignored if the threshold + * has not been reached). */ - private List discardNonExplicitTransformers(List allTransformers, String sourceMimetype, - long sourceSize, String targetMimetype, TransformationOptions options) + private List sortTransformers(List possibleTransformers) { - List transformers = new ArrayList(2); - boolean foundExplicit = false; + Collections.sort(possibleTransformers); - for (ContentTransformer transformer : allTransformers) + List transformers = new ArrayList(possibleTransformers.size()); + for (TransformerSortData possibleTransformer: possibleTransformers) { - if (transformer.isExplicitTransformation(sourceMimetype, targetMimetype, options) == true) - { - if (foundExplicit == false) - { - transformers.clear(); - foundExplicit = true; - } - transformers.add(transformer); - } - else - { - if (foundExplicit == false) - { - transformers.add(transformer); - } - } + transformers.add(possibleTransformer.transformer); } return transformers; } - - // sort by performance (quicker is "better") - private List sortTransformers(List transformers, - String sourceMimetype, long sourceSize, String targetMimetype, - TransformationOptions options) + + private class TransformerSortData implements Comparable { - final Map activeTransformers = new HashMap(); - for (ContentTransformer transformer : transformers) + private final ContentTransformer transformer; + private final int priority; + private long averageTime = -1; + + TransformerSortData(ContentTransformer transformer, String sourceMimetype, String targetMimetype, int priority) { - long transformationTime = transformer.getTransformationTime(); - activeTransformers.put(transformer, transformationTime); + this.transformer = transformer; + this.priority = priority; + + TransformerStatistics stats = transformerConfig.getStatistics(transformer, sourceMimetype, targetMimetype); + long threashold = transformerConfig.getThresholdCount(transformer, sourceMimetype, targetMimetype); + averageTime = (stats.getCount() < threashold) ? 0 : stats.getAverageTime(); } - - List sorted = new ArrayList(activeTransformers.keySet()); - Collections.sort(sorted, new Comparator() { - @Override - public int compare(ContentTransformer a, ContentTransformer b) + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + (int) (averageTime ^ (averageTime >>> 32)); + result = prime * result + priority; + return result; + } + + @Override + public boolean equals(Object obj) + { + return transformer == ((TransformerSortData) obj).transformer; + } + + @Override + public int compareTo(TransformerSortData that) + { + int relativePriority = priority - that.priority; + if (relativePriority != 0) { - return activeTransformers.get(a).compareTo(activeTransformers.get(b)); + return relativePriority; } - }); - return sorted; + + long relativeTime = averageTime - that.averageTime; + return relativeTime > 0L ? 1 : relativeTime < 0L ? -1 : 0; + } } } diff --git a/source/java/org/alfresco/repo/content/transform/TransformerSelectorImplOriginal.java b/source/java/org/alfresco/repo/content/transform/TransformerSelectorImplOriginal.java new file mode 100644 index 0000000000..409f8af5e0 --- /dev/null +++ b/source/java/org/alfresco/repo/content/transform/TransformerSelectorImplOriginal.java @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2005-2012 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco 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 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Alfresco. If not, see . + */ +package org.alfresco.repo.content.transform; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.alfresco.service.cmr.repository.TransformationOptions; + +/** + * Implementation of a transformer selector that matches the code that was in place + * before a selector was introduced. Class is not used but exists to allow customers + * to maintain the previous approach if they really wish. + * + * @author Alan Davis + */ +public class TransformerSelectorImplOriginal implements TransformerSelector +{ + private ContentTransformerRegistry contentTransformerRegistry; + + public void setContentTransformerRegistry(ContentTransformerRegistry contentTransformerRegistry) + { + this.contentTransformerRegistry = contentTransformerRegistry; + } + + @Override + public List selectTransformers( String sourceMimetype, long sourceSize, + String targetMimetype, TransformationOptions options) + { + List transformers = contentTransformerRegistry.getTransformers(); + transformers = findTransformers(transformers, sourceMimetype, sourceSize, targetMimetype, options); + transformers = discardNonExplicitTransformers(transformers, sourceMimetype, sourceSize, targetMimetype, options); + transformers = sortTransformers(transformers, sourceMimetype, sourceSize, targetMimetype, options); + return transformers; + } + + /** + * Reduces the list of transformers down to only those capable of doing the transformation. + */ + private List findTransformers(List allTransformers, String sourceMimetype, + long sourceSize, String targetMimetype, TransformationOptions options) + { + List transformers = new ArrayList(2); + + for (ContentTransformer transformer : allTransformers) + { + if (transformer.isTransformable(sourceMimetype, sourceSize, targetMimetype, options) == true) + { + transformers.add(transformer); + } + } + return transformers; + } + + /** + * Discards non explicit transformers if there are any explicit ones. + */ + private List discardNonExplicitTransformers(List allTransformers, String sourceMimetype, + long sourceSize, String targetMimetype, TransformationOptions options) + { + List transformers = new ArrayList(2); + boolean foundExplicit = false; + + for (ContentTransformer transformer : allTransformers) + { + if (transformer.isExplicitTransformation(sourceMimetype, targetMimetype, options) == true) + { + if (foundExplicit == false) + { + transformers.clear(); + foundExplicit = true; + } + transformers.add(transformer); + } + else + { + if (foundExplicit == false) + { + transformers.add(transformer); + } + } + } + return transformers; + } + + // sort by performance (quicker is "better") + private List sortTransformers(List transformers, + String sourceMimetype, long sourceSize, String targetMimetype, + TransformationOptions options) + { + final Map activeTransformers = new HashMap(); + for (ContentTransformer transformer : transformers) + { + long transformationTime = transformer.getTransformationTime(sourceMimetype, targetMimetype); + activeTransformers.put(transformer, transformationTime); + } + + List sorted = new ArrayList(activeTransformers.keySet()); + Collections.sort(sorted, new Comparator() { + @Override + public int compare(ContentTransformer a, ContentTransformer b) + { + return activeTransformers.get(a).compareTo(activeTransformers.get(b)); + } + }); + return sorted; + } +} diff --git a/source/java/org/alfresco/repo/content/transform/TransformerStatistics.java b/source/java/org/alfresco/repo/content/transform/TransformerStatistics.java new file mode 100644 index 0000000000..a5d06f2719 --- /dev/null +++ b/source/java/org/alfresco/repo/content/transform/TransformerStatistics.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2005-2012 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco 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 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Alfresco. If not, see . + */ +package org.alfresco.repo.content.transform; + + +/** + * Interface to obtain the configuration and performance data for every + * source, target and transformer combination. + * + * @author Alan Davis + */ +public interface TransformerStatistics +{ + /** + * @return the extension of the source mimetype of the transformer. + */ + public String getSourceExt(); + + /** + * @return the extension of the target mimetype of the transformer. + */ + public String getTargetExt(); + + /** + * @return the name of the parent transformer. + */ + public String getTransformerName(); + + /** + * @return the number of time the transformer has been called. + */ + public long getCount(); + + /** + * @param count overrides the number of time the transformer has been called. + */ + public void setCount(long count); + + /** + * @return the number of time the transformer has failed. + */ + public long getErrorCount(); + + /** + * @param errorCount overrides the number of time the transformer has failed. + */ + public void setErrorCount(long errorCount); + + /** + * @return the average time taken by the the transformer. + */ + public long getAverageTime(); + + /** + * @param averageTime overrides the average time taken by the the transformer. + */ + public void setAverageTime(long averageTime); + + /** + * @return true if this is the summary of all transformations done + * by a transformer rather than just between two specific mimetypes. + */ + public boolean isSummary(); + + /** + * @param transformationTime to be added to this TransformationData and its parents. + */ + public void recordTime(long transformationTime); + + /** + * Adds 1 to the error count of this TransformationData and its parents. + */ + public void recordError(); +} \ No newline at end of file diff --git a/source/java/org/alfresco/repo/content/transform/TransformerStatisticsImpl.java b/source/java/org/alfresco/repo/content/transform/TransformerStatisticsImpl.java new file mode 100644 index 0000000000..1ccd185f5b --- /dev/null +++ b/source/java/org/alfresco/repo/content/transform/TransformerStatisticsImpl.java @@ -0,0 +1,296 @@ +/* + * Copyright (C) 2005-2012 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco 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 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Alfresco. If not, see . + */ +package org.alfresco.repo.content.transform; + +import static org.alfresco.repo.content.transform.TransformerConfig.ANY; + +import org.alfresco.service.cmr.repository.MimetypeService; +import org.alfresco.service.cmr.repository.TransformationOptionLimits; + + +/** + * Implementation of a {@link TransformerStatistics}. + * + * @author Alan Davis + */ +// TODO These values should be made visible via JMX. +public class TransformerStatisticsImpl implements TransformerStatistics +{ + private final MimetypeService mimetypeService; + private final String sourceMimetype; + private final String targetMimetype; + private final ContentTransformer transformer; + private final TransformerStatistics parent; + private final long errorTime; + + private double averageTime; + private long count = 0L; + private long errorCount = 0L; + + public TransformerStatisticsImpl(MimetypeService mimetypeService, String sourceMimetype, String targetMimetype, + ContentTransformer transformer, TransformerStatistics parent, long errorTime, + long initialAverageTime, long initialCount) + { + this.mimetypeService = mimetypeService; + this.sourceMimetype = sourceMimetype; + this.targetMimetype = targetMimetype; + this.transformer = transformer; + this.parent = parent; + this.errorTime = errorTime; + + averageTime = initialAverageTime; + count = initialCount; + } + + @Override + public String getSourceExt() + { + return ANY.equals(sourceMimetype) ? ANY : mimetypeService.getExtension(sourceMimetype); + } + + @Override + public String getTargetExt() + { + return ANY.equals(targetMimetype) ? ANY : mimetypeService.getExtension(targetMimetype); + } + + @Override + public String getTransformerName() + { + return transformer == null ? TransformerConfig.SUMMARY_TRANSFORMER_NAME : transformer.getName(); + } + + @Override + public synchronized void recordTime(long transformationTime) + { + if (count == Long.MAX_VALUE) + { + // we have reached the max count - reduce it by half + // the average fluctuation won't be extreme + count /= 2L; + } + // adjust the average + count++; + double diffTime = ((double) transformationTime) - averageTime; + averageTime += diffTime / (double) count; + + if (parent != null) + { + parent.recordTime(transformationTime); + } + } + + @Override + public synchronized void recordError() + { + if (errorCount < Long.MAX_VALUE) + { + errorCount++; + } + if (errorTime > 0) + { + recordTime(errorTime); + } + if (parent != null) + { + parent.recordError(); + } + } + + @Override + public long getCount() + { + return count; + } + + @Override + public void setCount(long count) + { + this.count = count; + } + + @Override + public long getErrorCount() + { + return errorCount; + } + + @Override + public void setErrorCount(long errorCount) + { + this.errorCount = errorCount; + } + + @Override + public long getAverageTime() + { + return (long)averageTime; + } + + @Override + public void setAverageTime(long averageTime) + { + this.averageTime = (double)averageTime; + } + + public boolean isSummary() + { + return TransformerConfig.ANY.equals(sourceMimetype) && TransformerConfig.ANY.equals(targetMimetype); + } + + + + + + + //////////////////////////////////////// TODO Split into summary class /////////////////////////////////// + + + + + +// private enum Property +// { +// priority(true) +// { +// String getValue(TransformerData bean) +// { +// return Integer.toString(bean.getPriority()); +// } +// void setValue(TransformerData bean, String value) +// { +// bean.setPriority(Integer.valueOf(value)); +// } +// }, +// +// averageTime(false) +// { +// String getValue(TransformerData bean) +// { +// return Integer.toString(bean.getPriority()); +// } +// }, +// +// count(false) +// { +// String getValue(TransformerData bean) +// { +// return Integer.toString(bean.getPriority()); +// } +// }, +// +// errors(false) +// { +// String getValue(TransformerData bean) +// { +// return Integer.toString(bean.getPriority()); +// } +// }; +// +// private final boolean updatable; +// +// Property(boolean updatable) +// { +// this.updatable = updatable; +// } +// +// abstract String getValue(TransformerData bean); +// +// void setValue(TransformerData bean, String value) +// { +// } +// +// public boolean isUpdatable() +// { +// return updatable; +// } +// +// public static Set getNames() +// { +// Set names = new HashSet(); +// for (Property property: Property.class.getEnumConstants()) +// { +// names.add(property.name()); +// } +// return names; +// } +// }; +// +// public List getId() +// { +// List id = super.getId(); +// +// id.add(transformerName); +// +// if (TransformerConfig.ANY.equals(sourceExt)) +// { +// id.add(sourceExt); +// } +// +// if (TransformerConfig.ANY.equals(targetExt)) +// { +// id.add(targetExt); +// } +// +// return id; +// } +// +// public boolean isUpdateable(String name) +// { +// return Enum.valueOf(Property.class, name).isUpdatable(); +// } +// +// @Override +// protected PropertyBackedBeanState createInitialState() throws IOException +// { +// return new PropertyBackedBeanState() +// { +// +// @Override +// public Set getPropertyNames() +// { +// return Property.getNames(); +// } +// +// @Override +// public String getProperty(String name) +// { +// return Enum.valueOf(Property.class, name).getValue(TransformerDataImpl.this); +// } +// +// @Override +// public void setProperty(String name, String value) +// { +// Enum.valueOf(Property.class, name).setValue(TransformerDataImpl.this, value); +// } +// +// @Override +// public void start() +// { +// ; +// } +// +// @Override +// public void stop() +// { +// ; +// } +// }; +// } +} diff --git a/source/java/org/alfresco/repo/management/subsystems/AbstractPropertyBackedBean.java b/source/java/org/alfresco/repo/management/subsystems/AbstractPropertyBackedBean.java index 42dcfb3906..5032bd293c 100644 --- a/source/java/org/alfresco/repo/management/subsystems/AbstractPropertyBackedBean.java +++ b/source/java/org/alfresco/repo/management/subsystems/AbstractPropertyBackedBean.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2010 Alfresco Software Limited. + * Copyright (C) 2005-2012 Alfresco Software Limited. * * This file is part of Alfresco * @@ -20,6 +20,7 @@ package org.alfresco.repo.management.subsystems; import java.io.IOException; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -96,6 +97,41 @@ public abstract class AbstractPropertyBackedBean implements PropertyBackedBean, /** Lock for concurrent access. */ protected ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + /** + * Used in conjunction with {@link #localSetProperties} to control setting of + * properties from either a JMX client or by code in the local Alfresco + * node calling {@link AbstractPropertyBackedBean#setProperties(Map)} or + * {@link AbstractPropertyBackedBean#setProperty(String, String)}. + * Is true when there is a nested call to either of these + * methods. This is the case when there is an MBean AND one of these method was + * NOT originally called from that MBean (it is a local code). + */ + private ThreadLocal nestedCall = new ThreadLocal() + { + @Override + protected Boolean initialValue() + { + return false; + } + }; + + /** + * Used in conjunction with {@link #nestedCall} to control setting of + * properties from either a JMX client or by code in the local Alfresco + * node calling {@link AbstractPropertyBackedBean#setProperties(Map)} or + * {@link AbstractPropertyBackedBean#setProperty(String, String)}. + * Is set to true when there is a nested call back from + * a JMX bean. + */ + private ThreadLocal localSetProperties = new ThreadLocal() + { + @Override + protected Boolean initialValue() + { + return false; + } + }; + /** The logger. */ private static Log logger = LogFactory.getLog(AbstractPropertyBackedBean.class); @@ -554,74 +590,249 @@ public abstract class AbstractPropertyBackedBean implements PropertyBackedBean, } } + private void setPropertyInternal(String name, String value) + { + // Bring down the bean. The caller may have already broadcast this across the cluster + stop(false); + doInit(); + this.state.setProperty(name, value); + } + + private void setPropertiesInternal(Map properties) + { + // Bring down the bean. The caller may have already broadcast this across the cluster + stop(false); + doInit(); + + Map previousValues = new HashMap(properties.size() * 2); + try + { + // Set each of the properties and back up their previous values just in case + for (Map.Entry entry : properties.entrySet()) + { + String property = entry.getKey(); + String previousValue = this.state.getProperty(property); + this.state.setProperty(property, entry.getValue()); + previousValues.put(property, previousValue); + } + + // Attempt to start locally + start(false, true); + + // We still haven't broadcast the start - a persist is required first so this will be done by the caller + } + catch (Exception e) + { + // Oh dear - something went wrong. So restore previous state before rethrowing + for (Map.Entry entry : previousValues.entrySet()) + { + this.state.setProperty(entry.getKey(), entry.getValue()); + } + + // Bring the bean back up across the cluster + start(true, false); + if (e instanceof RuntimeException) + { + throw (RuntimeException) e; + } + throw new IllegalStateException(e); + } + } + /** * {@inheritDoc} + * + *

When called from code within the local node the values are saved to the + * database in the Enterprise edition and will be visible in a JMX client.

+ * + * @param name + * @param value */ public void setProperty(String name, String value) { - this.lock.writeLock().lock(); - try + if (logger.isDebugEnabled()) { - // Bring down the bean. The caller may have already broadcast this across the cluster - stop(false); - doInit(); - this.state.setProperty(name, value); + logger.debug("setProperty("+name+','+value+")"); } - finally + if (!nestedCall.get()) { - this.lock.writeLock().unlock(); - } - } - - public void setProperties(Map properties) - { - this.lock.writeLock().lock(); - try - { - // Bring down the bean. The caller may have already broadcast this across the cluster - stop(false); - doInit(); - - Map previousValues = new HashMap(properties.size() * 2); + nestedCall.set(true); + this.lock.writeLock().lock(); try { - // Set each of the properties and back up their previous values just in case - for (Map.Entry entry : properties.entrySet()) + boolean mBeanInfoChange = !getPropertyNames().contains(name); + + // When setting properties locally AND there is an MBean, the following broadcast + // results in a call to the MBean's setAttributes method, which in turn results + // in a nested call back. The call back sets the values in this bean and + // localSetProperties will be set to true. The MBean persists the changes and the + // broadcast method returns. If there is no MBean (community edition) OR when + // initiated from the MBean (say setting a value via JConsole), nothing happens + // as a result of the broadcast. + logger.debug("setProperty() broadcastSetProperties"); + this.registry.broadcastSetProperty(this, name, value); + + if (localSetProperties.get()) { - String property = entry.getKey(); - String previousValue = this.state.getProperty(property); - this.state.setProperty(property, entry.getValue()); - previousValues.put(property, previousValue); + if (mBeanInfoChange) + { + // Re register the bean so new properties are visible in JConsole which does + // not check MBeanInfo for changes otherwise. + logger.debug("setProperty() destroy"); + destroy(false); + + // Attempt to start locally + start(false, true); + } + } + else + { + logger.debug("setProperty() setPropertyInternal"); + setPropertyInternal(name, value); } - - // Attempt to start locally - start(false, true); - - // We still haven't broadcast the start - a persist is required first so this will be done by the caller } - catch (Exception e) + finally { - // Oh dear - something went wrong. So restore previous state before rethrowing - for (Map.Entry entry : previousValues.entrySet()) + localSetProperties.set(false); + nestedCall.set(false); + this.lock.writeLock().unlock(); + } + } + else + { + // A nested call indicates there is a MBean and that this method was + // NOT originally called from that MBean. + localSetProperties.set(true); + + logger.debug("setProperty() callback setPropertyInternal"); + setPropertyInternal(name, value); + } + } + + /** + * {@inheritDoc} + * + *

When called from code within the local node the values are saved to the + * database in the Enterprise edition and will be visible in a JMX client.

+ * + * @param properties to be saved. + */ + public void setProperties(Map properties) + { + if (logger.isDebugEnabled()) + { + logger.debug("setProperties("+properties+")"); + } + if (!nestedCall.get()) + { + nestedCall.set(true); + + boolean hadWriteLock = this.lock.isWriteLockedByCurrentThread(); + if (!hadWriteLock) + { + this.lock.writeLock().lock(); + } + try + { + boolean mBeanInfoChange = !getPropertyNames().containsAll(properties.keySet()); + + // When setting properties locally AND there is an MBean, the following broadcast + // results in a call to the MBean's setAttributes method, which in turn results + // in a nested call back. The call back sets the values in this bean and + // localSetProperties will be set to true. The MBean persists the changes and the + // broadcast method returns. If there is no MBean (community edition) OR when + // initiated from the MBean (say setting a value via JConsole), nothing happens + // as a result of the broadcast. + logger.debug("setProperties() broadcastSetProperties"); + this.registry.broadcastSetProperties(this, properties); + + if (localSetProperties.get()) { - this.state.setProperty(entry.getKey(), entry.getValue()); + if (mBeanInfoChange) + { + // Re register the bean so new properties are visible in JConsole which does + // not check MBeanInfo for changes otherwise. + logger.debug("setProperties() destroy"); + destroy(false); + + // Attempt to start locally + start(true, false); + } } - - // Bring the bean back up across the cluster - start(true, false); - if (e instanceof RuntimeException) + else { - throw (RuntimeException) e; + logger.debug("setProperties() setPropertiesInternal"); + setPropertiesInternal(properties); } - throw new IllegalStateException(e); + } + finally + { + localSetProperties.set(false); + nestedCall.set(false); + if (!hadWriteLock) + { + this.lock.writeLock().unlock(); + } + } + } + else + { + // A nested call indicates there is a MBean and that this method was + // NOT originally called from that MBean. + localSetProperties.set(true); + + logger.debug("setProperties() callback setPropertiesInternal"); + setPropertiesInternal(properties); + } + } + + /** + * Removes a property added by code within the local node. + * + * @param propertyNames to be removed. + */ + public void removeProperty(String name) + { + removeProperties(Collections.singleton(name)); + } + + /** + * Removes properties added by code within the local node. + * + * @param propertyNames to be removed. + */ + public void removeProperties(Collection propertyNames) + { + if (logger.isDebugEnabled()) + { + logger.debug("removeProperties("+propertyNames+")"); + } + this.lock.writeLock().lock(); + try + { + Set originalPropertyNames = state.getPropertyNames(); + Map propertiesToKeep = new HashMap(originalPropertyNames.size()*2); + for (String name: originalPropertyNames) + { + if (!propertyNames.contains(name)) + { + propertiesToKeep.put(name, state.getProperty(name)); + } + } + + // Check just in case there is nothing to do. + if (propertiesToKeep.size() != originalPropertyNames.size()) + { + destroy(true); + setProperties(propertiesToKeep); } } finally { this.lock.writeLock().unlock(); } - } + /** * {@inheritDoc} */ diff --git a/source/java/org/alfresco/repo/management/subsystems/DefaultPropertyBackedBeanRegistry.java b/source/java/org/alfresco/repo/management/subsystems/DefaultPropertyBackedBeanRegistry.java index 69637cb276..8a7f9916e1 100644 --- a/source/java/org/alfresco/repo/management/subsystems/DefaultPropertyBackedBeanRegistry.java +++ b/source/java/org/alfresco/repo/management/subsystems/DefaultPropertyBackedBeanRegistry.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2010 Alfresco Software Limited. + * Copyright (C) 2005-2012 Alfresco Software Limited. * * This file is part of Alfresco * @@ -20,6 +20,7 @@ package org.alfresco.repo.management.subsystems; import java.util.LinkedList; import java.util.List; +import java.util.Map; import org.alfresco.repo.domain.schema.SchemaAvailableEvent; import org.springframework.context.ApplicationEvent; @@ -98,6 +99,30 @@ public class DefaultPropertyBackedBeanRegistry implements PropertyBackedBeanRegi broadcastEvent(new PropertyBackedBeanStoppedEvent(bean)); } + /* + * (non-Javadoc) + * @see + * org.alfresco.repo.management.subsystems.PropertyBackedBeanRegistry#broadcastSetProperty(org.alfresco.repo.management + * .subsystems.PropertyBackedBean, String, String) + */ + @Override + public void broadcastSetProperty(PropertyBackedBean bean, String name, String value) + { + broadcastEvent(new PropertyBackedBeanSetPropertyEvent(bean, name, value)); + } + + /* + * (non-Javadoc) + * @see + * org.alfresco.repo.management.subsystems.PropertyBackedBeanRegistry#broadcastSetProperties(org.alfresco.repo.management + * .subsystems.PropertyBackedBean, Map) + */ + @Override + public void broadcastSetProperties(PropertyBackedBean bean, Map properties) + { + broadcastEvent(new PropertyBackedBeanSetPropertiesEvent(bean, properties)); + } + /** * Broadcast event. * diff --git a/source/java/org/alfresco/repo/management/subsystems/PropertyBackedBeanRegistry.java b/source/java/org/alfresco/repo/management/subsystems/PropertyBackedBeanRegistry.java index 4814c45a29..45e868bbe0 100644 --- a/source/java/org/alfresco/repo/management/subsystems/PropertyBackedBeanRegistry.java +++ b/source/java/org/alfresco/repo/management/subsystems/PropertyBackedBeanRegistry.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2010 Alfresco Software Limited. + * Copyright (C) 2005-2012 Alfresco Software Limited. * * This file is part of Alfresco * @@ -18,6 +18,8 @@ */ package org.alfresco.repo.management.subsystems; +import java.util.Map; + import org.springframework.context.ApplicationListener; /** @@ -75,4 +77,26 @@ public interface PropertyBackedBeanRegistry * the bean */ public void broadcastStop(PropertyBackedBean bean); + + /** + * Signals that a {@link PropertyBackedBean} has been asked to + * update a property. + * + * @param bean + * the bean + * @param name + * the name + * @param value + * the value + */ + public void broadcastSetProperty(PropertyBackedBean bean, String name, String value); + + /** + * Signals that a {@link PropertyBackedBean} has been asked to + * update properties. + * + * @param bean + * the bean + */ + public void broadcastSetProperties(PropertyBackedBean bean, Map properties); } diff --git a/source/java/org/alfresco/repo/management/subsystems/PropertyBackedBeanSetPropertiesEvent.java b/source/java/org/alfresco/repo/management/subsystems/PropertyBackedBeanSetPropertiesEvent.java new file mode 100644 index 0000000000..32bf8ce64e --- /dev/null +++ b/source/java/org/alfresco/repo/management/subsystems/PropertyBackedBeanSetPropertiesEvent.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2005-2012 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco 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 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Alfresco. If not, see . + */ +package org.alfresco.repo.management.subsystems; + +import java.util.Map; + + +/** + * An event emitted before a {@link PropertyBackedBean} updates its properties. + * + * @author Alan Davis + */ +public class PropertyBackedBeanSetPropertiesEvent extends PropertyBackedBeanEvent +{ + private static final long serialVersionUID = 7530572539759535003L; + + private Map properties; + + /** + * The Constructor. + * + * @param source + * the source of the event + */ + public PropertyBackedBeanSetPropertiesEvent(PropertyBackedBean source, Map properties) + { + super(source); + this.properties = properties; + } + + public Map getProperties() + { + return properties; + } +} diff --git a/source/java/org/alfresco/repo/management/subsystems/PropertyBackedBeanSetPropertyEvent.java b/source/java/org/alfresco/repo/management/subsystems/PropertyBackedBeanSetPropertyEvent.java new file mode 100644 index 0000000000..d2bf15f738 --- /dev/null +++ b/source/java/org/alfresco/repo/management/subsystems/PropertyBackedBeanSetPropertyEvent.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2005-2012 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco 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 of the License, or + * (at your option) any later version. + * + * Alfresco 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 Alfresco. If not, see . + */ +package org.alfresco.repo.management.subsystems; + + + +/** + * An event emitted before a {@link PropertyBackedBean} updates a property. + * + * @author Alan Davis + */ +public class PropertyBackedBeanSetPropertyEvent extends PropertyBackedBeanEvent +{ + private static final long serialVersionUID = 7421919310357212865L; + + private String name; + private String value; + + /** + * The Constructor. + * + * @param source + * the source of the event + */ + public PropertyBackedBeanSetPropertyEvent(PropertyBackedBean source, String name, String value) + { + super(source); + this.name = name; + this.value = value; + } + + public String getName() + { + return name; + } + + public String getValue() + { + return value; + } +} diff --git a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexerImpl.java b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexerImpl.java index d8beb345b5..ef0711afd3 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexerImpl.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexerImpl.java @@ -1430,16 +1430,17 @@ public class ADMLuceneIndexerImpl extends AbstractLuceneIndexerImpl imp // We have a reader, so use it boolean readerReady = true; // transform if necessary (it is not a UTF-8 text document) - if (!EqualsHelper.nullSafeEquals(reader.getMimetype(), MimetypeMap.MIMETYPE_TEXT_PLAIN) || !EqualsHelper.nullSafeEquals(reader.getEncoding(), "UTF-8")) + String sourceMimetype = reader.getMimetype(); + if (!EqualsHelper.nullSafeEquals(sourceMimetype, MimetypeMap.MIMETYPE_TEXT_PLAIN) || !EqualsHelper.nullSafeEquals(reader.getEncoding(), "UTF-8")) { try { // get the transformer TransformationOptions options = new TransformationOptions(); options.setSourceNodeRef(nodeRef); - transformerDebug.pushAvailable(reader.getContentUrl(), reader.getMimetype(), MimetypeMap.MIMETYPE_TEXT_PLAIN, options); + transformerDebug.pushAvailable(reader.getContentUrl(), sourceMimetype, MimetypeMap.MIMETYPE_TEXT_PLAIN, options); long sourceSize = reader.getSize(); - List transformers = contentService.getActiveTransformers(reader.getMimetype(), sourceSize, MimetypeMap.MIMETYPE_TEXT_PLAIN, options); + List transformers = contentService.getActiveTransformers(sourceMimetype, sourceSize, MimetypeMap.MIMETYPE_TEXT_PLAIN, options); transformerDebug.availableTransformers(transformers, sourceSize, "ADMLuceneIndexer"); if (transformers.isEmpty()) @@ -1458,7 +1459,7 @@ public class ADMLuceneIndexerImpl extends AbstractLuceneIndexerImpl imp doc.add(new Field(attributeName, NOT_INDEXED_NO_TRANSFORMATION, Field.Store.NO, Field.Index.TOKENIZED, Field.TermVector.NO)); } // is this transformer good enough? - else if (indexAtomicPropertiesOnly && transformers.get(0).getTransformationTime() > maxAtomicTransformationTime) + else if (indexAtomicPropertiesOnly && transformers.get(0).getTransformationTime(sourceMimetype, MimetypeMap.MIMETYPE_TEXT_PLAIN) > maxAtomicTransformationTime) { // only indexing atomic properties // indexing will take too long, so push it to the background diff --git a/source/java/org/alfresco/service/cmr/repository/TransformationOptionLimits.java b/source/java/org/alfresco/service/cmr/repository/TransformationOptionLimits.java index 9ca790e1e5..295e7578ba 100644 --- a/source/java/org/alfresco/service/cmr/repository/TransformationOptionLimits.java +++ b/source/java/org/alfresco/service/cmr/repository/TransformationOptionLimits.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2012 Alfresco Software Limited. + * Copyright (C) 2005-2013 Alfresco Software Limited. * * This file is part of Alfresco * @@ -150,6 +150,18 @@ public class TransformationOptionLimits pages.setLimit(pageLimit, PAGES_MESSAGE); } + // --------------- Enabled --------------- + + /** + * Indicates if the limits allow a transformation to take place at all. + * If any of the limits are 0, it would not be possible. + * @return true if a transformation is possible. + */ + public boolean supported() + { + return time.supported() && kbytes.supported() && pages.supported(); + } + // --------------- Map --------------- public Map toMap(Map optionsMap) { diff --git a/source/java/org/alfresco/service/cmr/repository/TransformationOptionLimitsMap.java b/source/java/org/alfresco/service/cmr/repository/TransformationOptionLimitsMap.java index 876537a730..10edd47dc3 100644 --- a/source/java/org/alfresco/service/cmr/repository/TransformationOptionLimitsMap.java +++ b/source/java/org/alfresco/service/cmr/repository/TransformationOptionLimitsMap.java @@ -37,7 +37,7 @@ import org.apache.commons.logging.LogFactory; * <bean id="mimetypeLimits.OpenOffice" class="org.alfresco.service.cmr.repository.TransformationOptionLimitsMap"> * <constructor-arg> * <value> - * * txt TransformationOptionLimits ${content.transformer.OpenOffice.mimeTypeLimits.txt.pdf.maxSourceSizeKBytes} ; + * * txt maxSourceSizeKBytes ${content.transformer.OpenOffice.mimeTypeLimits.txt.pdf.maxSourceSizeKBytes} ; * doc pdf maxSourceSizeKBytes ${content.transformer.OpenOffice.mimeTypeLimits.doc.pdf.maxSourceSizeKBytes} * </value> * </constructor-arg> diff --git a/source/java/org/alfresco/service/cmr/repository/TransformationOptionPair.java b/source/java/org/alfresco/service/cmr/repository/TransformationOptionPair.java index 31eb29f7c3..ac0b8fc8b8 100644 --- a/source/java/org/alfresco/service/cmr/repository/TransformationOptionPair.java +++ b/source/java/org/alfresco/service/cmr/repository/TransformationOptionPair.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2012 Alfresco Software Limited. + * Copyright (C) 2005-2013 Alfresco Software Limited. * * This file is part of Alfresco * @@ -104,6 +104,16 @@ public class TransformationOptionPair return minSet(getMax(), getLimit()); } + /** + * Indicates if the limit allows a transformation to take place at all. + * If 0, it would not be possible. + * @return true if a transformation is possible. + */ + public boolean supported() + { + return getValue() != 0; + } + public Action getAction() { return @@ -112,6 +122,19 @@ public class TransformationOptionPair : null; } + public String toString(String max, String limit) + { + if (getMax() >= 0) + { + return max+'='+getValue(); + } + if (getLimit() >= 0) + { + return limit+'='+getValue(); + } + return null; + } + /** * Returns the lower of the two value supplied, ignoring values less than * 0 unless both are less than zero. diff --git a/source/java/org/alfresco/service/cmr/repository/TransformationOptions.java b/source/java/org/alfresco/service/cmr/repository/TransformationOptions.java index a42c29d131..ad426fb32a 100644 --- a/source/java/org/alfresco/service/cmr/repository/TransformationOptions.java +++ b/source/java/org/alfresco/service/cmr/repository/TransformationOptions.java @@ -517,7 +517,7 @@ public class TransformationOptions implements Cloneable *

  • {@link #OPT_INCLUDE_EMBEDDED}
  • *
  • {@link TransformationOptionLimits#OPT_TIMEOUT_MS}
  • *
  • {@link TransformationOptionLimits#OPT_READ_LIMIT_TIME_MS}
  • - *
  • {@link TransformationOptionLimits#OPT_MAX_SOURCE_SIZE_K_BYTES = "maxSourceSizeKBytes"; + *
  • {@link TransformationOptionLimits#OPT_MAX_SOURCE_SIZE_K_BYTES
  • *
  • {@link TransformationOptionLimits#OPT_READ_LIMIT_K_BYTES}
  • *
  • {@link TransformationOptionLimits#OPT_MAX_PAGES}
  • *
  • {@link TransformationOptionLimits#OPT_PAGE_LIMIT}