REPO-5203 Remove legacy transformers (#181)

Now that the T-Engines provide parity with in process legacy transforms and metadata extract, the legacy transform code is now being removed. This will allow the documentation to be greatly simplified and a number of libraries to be removed.

Custom legacy transforms need to be moved to T-Engines. ACS 6 still provides a version where both may be run in parallel. New versions of the document transform engine (DTE) and media management (MM) are planned for ACS 7.
This commit is contained in:
Alan Davis
2021-01-03 13:20:22 +00:00
committed by GitHub
parent affccc1b4d
commit 5d2c83c14b
229 changed files with 351 additions and 42025 deletions

View File

@@ -84,7 +84,7 @@ jobs:
- docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:11.7 postgres -c 'max_connections=300'
- docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.15.8
- docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.3.6
script: travis_wait 20 mvn -B test -pl repository -Dtest=AppContext03TestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco -Dalfresco-pdf-renderer.url=http://localhost:8090/ -Djodconverter.url=http://localhost:8090/ -Dimg.url=http://localhost:8090/ -Dtika.url=http://localhost:8090/ -Dtransform.misc.url=http://localhost:8090/
script: travis_wait 20 mvn -B test -pl repository -Dtest=AppContext03TestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
- name: "Repository - AppContext04TestSuite"
before_script:
@@ -108,7 +108,7 @@ jobs:
- docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:11.7 postgres -c 'max_connections=300'
- docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.15.8
- docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.3.6
script: travis_wait 20 mvn -B test -pl repository -Dtest=AppContext06TestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco -Dalfresco-pdf-renderer.url=http://localhost:8090/ -Djodconverter.url=http://localhost:8090/ -Dimg.url=http://localhost:8090/ -Dtika.url=http://localhost:8090/ -Dtransform.misc.url=http://localhost:8090/
script: travis_wait 20 mvn -B test -pl repository -Dtest=AppContext06TestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
- name: "Repository - AppContextExtraTestSuite"
before_script:
@@ -122,7 +122,7 @@ jobs:
- docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:11.7 postgres -c 'max_connections=300'
- docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.15.8
- docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.3.6
script: travis_wait 20 mvn -B test -pl repository -Dtest=MiscContextTestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco -Dalfresco-pdf-renderer.url=http://localhost:8090/ -Djodconverter.url=http://localhost:8090/ -Dimg.url=http://localhost:8090/ -Dtika.url=http://localhost:8090/ -Dtransform.misc.url=http://localhost:8090/
script: travis_wait 20 mvn -B test -pl repository -Dtest=MiscContextTestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
- name: "Repository - SearchTestSuite"
before_script:
@@ -182,6 +182,7 @@ jobs:
before_script:
- docker run -d -p 5433:5432 -e POSTGRES_PASSWORD=alfresco -e POSTGRES_USER=alfresco -e POSTGRES_DB=alfresco postgres:11.7 postgres -c 'max_connections=300'
- docker run -d -p 61616:61616 -p 5672:5672 alfresco/alfresco-activemq:5.15.8
- docker run -d -p 8090:8090 -e JAVA_OPTS=" -Xms256m -Xmx256m" alfresco/alfresco-transform-core-aio:2.3.5
script: travis_wait 20 mvn -B test -pl remote-api -Dtest=AppContext04TestSuite -Ddb.driver=org.postgresql.Driver -Ddb.name=alfresco -Ddb.url=jdbc:postgresql://localhost:5433/alfresco -Ddb.username=alfresco -Ddb.password=alfresco
- name: "Remote-api - AppContextExtraTestSuite"

View File

@@ -662,7 +662,6 @@ public class MimetypeMap implements MimetypeService
boolean successReadingConfig = true;
if (jsonConfigFileFinder != null)
{
// This should not be "alfresco/mimetype" which is used for the in JVM jodconverter
successReadingConfig &= jsonConfigFileFinder.readFiles("alfresco/mimetypes", logger);
if (mimetypeJsonConfigDir != null && !mimetypeJsonConfigDir.isBlank())
{
@@ -877,11 +876,6 @@ public class MimetypeMap implements MimetypeService
*/
private MediaType detectType(String filename, ContentReader reader)
{
// Metadata metadata = new Metadata();
// if (filename != null)
// {
// metadata.add(Metadata.RESOURCE_NAME_KEY, filename);
// }
TikaInputStream inp = null;
try
{

View File

@@ -2,7 +2,7 @@
* #%L
* Alfresco Data model classes
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
@@ -33,8 +33,7 @@ import org.alfresco.api.AlfrescoPublicApi;
* same action might succeed, all other things not having changed.
* <p/>
* An example of this would be the case where a request to create a thumbnail
* has failed because the necessary thumbnailing software is not available e.g. because the OpenOffice.org process
* is not currently running.
* has failed because the necessary thumbnailing software is not available.
*
* @author Neil Mc Erlean
* @since 4.0.1

File diff suppressed because one or more lines are too long

View File

@@ -1,110 +0,0 @@
The authoritative ImageMagick license can be found at
http://www.imagemagick.org/script/license.php and ImageMagick notices at
http://www.imagemagick.org/www/Notice.html.
Before we get to the text of the license, lets just review what the license says in simple terms:
It allows you to:
* freely download and use ImageMagick software, in whole or in part, for personal, company internal, or commercial purposes;
* use ImageMagick software in packages or distributions that you create;
* link against a library under a different license;
* link code under a different license against a library under this license;
* merge code into a work under a different license;
* extend patent grants to any code using code under this license;
*and extend patent protection.
It forbids you to:
* redistribute any piece of ImageMagick-originated software without proper attribution;
* use any marks owned by ImageMagick Studio LLC in any way that might state or imply that ImageMagick Studio LLC endorses your distribution;
* use any marks owned by ImageMagick Studio LLC in any way that might state or imply that you created the ImageMagick software in question.
It requires you to:
* include a copy of the license in any redistribution you may make that includes ImageMagick software;
* provide clear attribution to ImageMagick Studio LLC for any distributions that include ImageMagick software.
It does not require you to:
* include the source of the ImageMagick software itself, or of any modifications you may have made to it, in any redistribution you may assemble that includes it;
* submit changes that you make to the software back to the ImageMagick Studio LLC (though such feedback is encouraged).
A few other clarifications include:
* ImageMagick is freely available without charge;
* you may include ImageMagick on any digital media as long as you comply with the terms of the license;
* you can give modified code away for free or sell it under the terms of the ImageMagick license or distribute the result under a different license, but you need to acknowledge the use of the ImageMagick software;
* the license is compatible with the GPL V3.
* when exporting the ImageMagick software, review its export classification.
Terms and Conditions for Use, Reproduction, and Distribution
The legally binding and authoritative terms and conditions for use, reproduction, and distribution of ImageMagick follow:
Copyright © 1999-2018 ImageMagick Studio LLC, a non-profit organization dedicated to making software imaging solutions freely available.
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
a. You must give any other recipients of the Work or Derivative Works a copy of this License; and
b. You must cause any modified files to carry prominent notices stating that You changed the files; and
c. You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
d. If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
How to Apply the License to your Work
To apply the ImageMagick License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information (don't include the brackets). The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the ImageMagick License (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy
of the License at
https://www.imagemagick.org/script/license.php
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations
under the License.

File diff suppressed because it is too large Load Diff

View File

@@ -45,7 +45,6 @@ commons-pool http://jakarta.apache.org/commons/
commons-validator http://jakarta.apache.org/commons/
ConcurrentLinkedHashMap http://code.google.com/p/concurrentlinkedhashmap/
Fast Infoset Project http://fi.java.net/
PDFBox http://pdfbox.apache.org/
Google Data Java Client Library http://code.google.com/p/gdata-java-client/
Geronimo Activation http://geronimo.apache.org/
Geronimo Annotation http://geronimo.apache.org/
@@ -191,10 +190,6 @@ truezip http://truezip.java.net/
icu4j http://icu-project.org/
=== Imagemagick ===
Imagemagick http://www.imagemagick.org/script/license.php
=== JSON license ===
JSon http://www.json.org/java/
@@ -211,16 +206,11 @@ libwmf http://wvware.sourceforge.net/libwmf.html
=== LGPL 2.1 ===
Hibernate http://www.hibernate.org/
jid3lib http://javamusictag.sourceforge.net/
JMagick http://sourceforge.net/projects/jmagick/
JODConverter http://jodconverter.sourceforge.net/
PDF Renderer http://java.net/projects/pdf-renderer
TinyMCE http://www.tinymce.com/
=== LGPL 3.0 ===
Gytheio https://github.com/Alfresco/gytheio
Jut.jar http://www.openoffice.org/licenses/lgpl_license.html
OpenOffice SDK http://www.openoffice.org/licenses/lgpl_license.html
=== MIT License ===
@@ -243,7 +233,6 @@ juniversalchardet http://code.google.com/p/juniversalchardet/
=== Mozilla Public License 2.0 ===
CCC2 http://www.webdetails.pt/ctools/ccc/
rhino-js http://www.mozilla.org/rhino/
LibreOffice http://www.libreoffice.org/
=== Oracle Binary Code License ===
@@ -279,7 +268,6 @@ The svn diff files with the details of the changes can be found in the following
=== Apache 2.0 License ====
acegi http://sourceforge.net/projects/acegisecurity/
commons-dbcp http://jakarta.apache.org/commons/
PDFBox http://pdfbox.apache.org/
Greenmail http://www.icegreen.com/greenmail/
POI http://poi.apache.org/
quartz http://quartz-scheduler.org/
@@ -297,12 +285,9 @@ TrueLicense http://truelicense.java.net/
=== LGPL 2.1 ===
Hibernate http://www.hibernate.org/
JODConverter http://jodconverter.sourceforge.net/
PDF Renderer http://java.net/projects/pdf-renderer
TinyMCE http://www.tinymce.com/
=== LGPL 3.0 ===
Jut.jar http://www.openoffice.org/licenses/lgpl_license.html
=== Mozilla Public License 2.0 ===
rhino-js http://www.mozilla.org/rhino/

View File

@@ -40,11 +40,6 @@ services:
-Daos.baseUrlOverwrite=http://localhost:8082/alfresco/aos
-Dmessaging.broker.url=\"failover:(tcp://activemq:61616)?timeout=3000&jms.useCompression=true\"
-DlocalTransform.core-aio.url=http://transform-core-aio:8090/
-Dalfresco-pdf-renderer.url=http://transform-core-aio:8090/
-Djodconverter.url=http://transform-core-aio:8090/
-Dimg.url=http://transform-core-aio:8090/
-Dtika.url=http://transform-core-aio:8090/
-Dtransform.misc.url=http://transform-core-aio:8090/
-Dimap.server.port=1143
-Dftp.port=1221
-Dcors.enabled=true

View File

@@ -239,11 +239,6 @@ log4j.logger.freemarker.runtime=
# Metadata extraction
log4j.logger.org.alfresco.repo.content.metadata.AbstractMappingMetadataExtracter=warn
# Reduces PDFont error level due to ALF-7105
log4j.logger.org.apache.pdfbox.pdmodel.font.PDSimpleFont=fatal
log4j.logger.org.apache.pdfbox.pdmodel.font.PDFont=fatal
log4j.logger.org.apache.pdfbox.pdmodel.font.PDCIDFont=fatal
# no index support
log4j.logger.org.alfresco.repo.search.impl.noindex.NoIndexIndexer=fatal
log4j.logger.org.alfresco.repo.search.impl.noindex.NoIndexSearchService=fatal
@@ -264,10 +259,7 @@ log4j.logger.org.alfresco.enterprise.repo.authorization.AuthorizationsConsistenc
log4j.logger.org.alfresco.heartbeat=info
# Transformations
log4j.logger.org.alfresco.repo.content.transform.JodContentTransformer=info
log4j.logger.org.alfresco.repo.content.transform.magick.ImageMagickContentTransformerWorker=info
log4j.logger.org.alfresco.repo.content.transform.pdfrenderer.AlfrescoPdfRendererContentTransformerWorker=info
log4j.logger.org.alfresco.repo.content.transform.TikaPoweredContentTransformer=info
#log4j.logger.org.alfresco.repo.content.transform.TransformerDebug=debug
log4j.logger.org.alfresco.repo.content.transform=info

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

25
pom.xml
View File

@@ -39,11 +39,9 @@
<maven.build.sourceVersion>11</maven.build.sourceVersion>
<dir.root>${project.build.directory}/alf_data</dir.root>
<img.exe>convert</img.exe>
<dependency.alfresco-hb-data-sender.version>1.0.12</dependency.alfresco-hb-data-sender.version>
<dependency.alfresco-mmt.version>6.0</dependency.alfresco-mmt.version>
<dependency.alfresco-pdf-renderer.version>1.1</dependency.alfresco-pdf-renderer.version>
<dependency.alfresco-trashcan-cleaner.version>2.3</dependency.alfresco-trashcan-cleaner.version>
<dependency.alfresco-jlan.version>7.1</dependency.alfresco-jlan.version>
<dependency.alfresco-server-root.version>6.0.1</dependency.alfresco-server-root.version>
@@ -61,7 +59,6 @@
<dependency.jackson-databind.version>2.11.2</dependency.jackson-databind.version>
<dependency.cxf.version>3.4.2</dependency.cxf.version>
<dependency.opencmis.version>1.0.0</dependency.opencmis.version>
<dependency.pdfbox.version>2.0.21</dependency.pdfbox.version>
<dependency.webscripts.version>8.15</dependency.webscripts.version>
<dependency.bouncycastle.version>1.68</dependency.bouncycastle.version>
<dependency.mockito-core.version>3.6.0</dependency.mockito-core.version>
@@ -82,8 +79,6 @@
<dependency.tika.version>1.25</dependency.tika.version>
<dependency.spring-security.version>5.4.1</dependency.spring-security.version>
<dependency.truezip.version>7.7.10</dependency.truezip.version>
<dependency.poi.version>4.1.2</dependency.poi.version>
<dependency.ooxml-schemas.version>1.4</dependency.ooxml-schemas.version>
<dependency.keycloak.version>11.0.0-alfresco-001</dependency.keycloak.version>
<dependency.jboss.logging.version>3.4.1.Final</dependency.jboss.logging.version>
<dependency.camel.version>2.24.2</dependency.camel.version>
@@ -165,20 +160,6 @@
<artifactId>alfresco-mmt</artifactId>
<version>${dependency.alfresco-mmt.version}</version>
</dependency>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-pdf-renderer</artifactId>
<version>${dependency.alfresco-pdf-renderer.version}</version>
<classifier>linux</classifier>
<type>tgz</type>
</dependency>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-pdf-renderer</artifactId>
<version>${dependency.alfresco-pdf-renderer.version}</version>
<classifier>win64</classifier>
<type>tgz</type>
</dependency>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-server-root</artifactId>
@@ -534,12 +515,6 @@
<artifactId>commons-compress</artifactId>
<version>1.20</version>
</dependency>
<!-- upgrade dependency from TIKA -->
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>${dependency.pdfbox.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>

View File

@@ -208,100 +208,6 @@
</exclusions>
</dependency>
</dependencies>
<profiles>
<!-- Profiles to extract the alfresco-pdf-renderer -->
<profile>
<id>win-alfresco-pdf-renderer-test</id>
<activation>
<os>
<family>windows</family>
</os>
</activation>
<dependencies>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-pdf-renderer</artifactId>
<classifier>win64</classifier>
<type>tgz</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<inherited>false</inherited>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>extract-alfresco-pdf-renderer-test</id>
<phase>generate-test-resources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<skip>${skipTests}</skip>
<target>
<echo message="Extracting alfresco-pdf-renderer (windows) for testing..." />
<mkdir dir="${project.build.directory}/test-binaries/alfresco-pdf-renderer" />
<untar compression="gzip" src="${settings.localRepository}/org/alfresco/alfresco-pdf-renderer/${dependency.alfresco-pdf-renderer.version}/alfresco-pdf-renderer-${dependency.alfresco-pdf-renderer.version}-win64.tgz" dest="${project.build.directory}/test-binaries/alfresco-pdf-renderer" />
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<alfresco-pdf-renderer.exe>${project.build.directory}/test-binaries/alfresco-pdf-renderer/alfresco-pdf-renderer</alfresco-pdf-renderer.exe>
</properties>
</profile>
<profile>
<id>linux-alfresco-pdf-renderer-test</id>
<activation>
<os>
<family>linux</family>
</os>
</activation>
<dependencies>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-pdf-renderer</artifactId>
<classifier>linux</classifier>
<type>tgz</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<inherited>false</inherited>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>extract-alfresco-pdf-renderer-test</id>
<phase>generate-test-resources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<skip>${skipTests}</skip>
<target>
<echo message="Extracting alfresco-pdf-renderer (linux) for testing..." />
<mkdir dir="${project.build.directory}/test-binaries/alfresco-pdf-renderer" />
<exec failonerror="true" executable="tar" dir="${project.build.directory}/test-binaries/alfresco-pdf-renderer">
<arg value="xf" />
<arg value="${settings.localRepository}/org/alfresco/alfresco-pdf-renderer/${dependency.alfresco-pdf-renderer.version}/alfresco-pdf-renderer-${dependency.alfresco-pdf-renderer.version}-linux.tgz" />
</exec>
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<alfresco-pdf-renderer.exe>${project.build.directory}/test-binaries/alfresco-pdf-renderer/alfresco-pdf-renderer</alfresco-pdf-renderer.exe>
</properties>
</profile>
</profiles>
<build>
<pluginManagement>
<plugins>
@@ -335,8 +241,6 @@
<!-- To prevent tests alfresco.log to be created in project roots and bother while synchronizing with SCM -->
<workingDirectory>${project.build.directory}</workingDirectory>
<systemPropertyVariables>
<alfresco-pdf-renderer.exe>${alfresco-pdf-renderer.exe}</alfresco-pdf-renderer.exe>
<!-- Database related properties -->
<db.url>${db.url}</db.url>
<db.driver>${db.driver}</db.driver>
@@ -344,7 +248,6 @@
<db.username>${db.username}</db.username>
<db.password>${db.password}</db.password>
<dir.root>${dir.root}</dir.root>
<img.exe>${img.exe}</img.exe>
<!-- BDE-91 -->
<alfresco.rmi.services.retries>30</alfresco.rmi.services.retries>
<alfresco.rmi.services.retryInterval>2000</alfresco.rmi.services.retryInterval>

View File

@@ -1,28 +1,28 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.webdav;
import java.util.Set;
@@ -82,8 +82,6 @@ public class UnlockMethod extends WebDAVMethod
{
if (!(strLockTokenHeader.startsWith("<") && strLockTokenHeader.endsWith(">")))
{
// ALF-13904: Header isn't correctly enclosed in < and > characters. Try correcting this
// to allow for Windows 7 + OpenOffice.org bug.
strLockTokenHeader = "<" + strLockTokenHeader + ">";
}
if (strLockTokenHeader.startsWith("<" + WebDAV.OPAQUE_LOCK_TOKEN) && strLockTokenHeader.endsWith(">"))

View File

@@ -20,7 +20,6 @@ admin-console.close=Close
admin-console.password.show=Show Password
admin-console.password.hide=Hide Password
admin-console.unavailable=Information is currently unavailable
admin-console.not.installed=Not Installed
admin-console.requesterror=We couldn't complete your request. Try again.

View File

@@ -20,7 +20,6 @@ admin-console.close=Zav\u0159\u00edt
admin-console.password.show=Zobrazit heslo
admin-console.password.hide=Skr\u00fdt heslo
admin-console.unavailable=Informace nejsou moment\u00e1ln\u011b k\u00a0dispozici
admin-console.not.installed=Nen\u00ed nainstalov\u00e1no
admin-console.requesterror=V\u00e1\u0161 po\u017eadavek nebylo mo\u017en\u00e9 dokon\u010dit. Zkuste to znovu.

View File

@@ -20,7 +20,6 @@ admin-console.close=Luk
admin-console.password.show=Vis adgangskode
admin-console.password.hide=Skjul adgangskode
admin-console.unavailable=Oplysningerne er i \u00f8jeblikket ikke tilg\u00e6ngelige
admin-console.not.installed=Ikke installeret
admin-console.requesterror=Vi kunne ikke fuldf\u00f8re anmodningen. Pr\u00f8v igen.

View File

@@ -20,7 +20,6 @@ admin-console.close=Schlie\u00dfen
admin-console.password.show=Passwort anzeigen
admin-console.password.hide=Passwort ausblenden
admin-console.unavailable=Information ist derzeit nicht verf\u00fcgbar
admin-console.not.installed=Nicht installiert
admin-console.requesterror=Die Anfrage konnte nicht durchgef\u00fchrt werden.

View File

@@ -20,7 +20,6 @@ admin-console.close=Cerrar
admin-console.password.show=Mostrar contrase\u00f1a
admin-console.password.hide=Ocultar contrase\u00f1a
admin-console.unavailable=La informaci\u00f3n no est\u00e1 disponible en este momento
admin-console.not.installed=No instalado
admin-console.requesterror=No se ha podido realizar la solicitud.

View File

@@ -20,7 +20,6 @@ admin-console.close=Sulje
admin-console.password.show=N\u00e4yt\u00e4 salasana
admin-console.password.hide=Piilota salasana
admin-console.unavailable=Tiedot eiv\u00e4t ole juuri nyt saatavilla
admin-console.not.installed=Ei asennettu
admin-console.requesterror=Pyynn\u00f6n suorittaminen ei onnistu. Yrit\u00e4 uudelleen.

View File

@@ -20,7 +20,6 @@ admin-console.close=Fermer
admin-console.password.show=Afficher le mot de passe
admin-console.password.hide=Masquer le mot de passe
admin-console.unavailable=Informations actuellement indisponibles
admin-console.not.installed=Pas install\u00e9
admin-console.requesterror=Echec de la requ\u00eate.

View File

@@ -20,7 +20,6 @@ admin-console.close=Chiudi
admin-console.password.show=Mostra password
admin-console.password.hide=Nascondi password
admin-console.unavailable=Le informazioni non sono al momento disponibili
admin-console.not.installed=Non installato
admin-console.requesterror=Impossibile completare la richiesta.

View File

@@ -20,7 +20,6 @@ admin-console.close=\u9589\u3058\u308b
admin-console.password.show=\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u8868\u793a\u3059\u308b
admin-console.password.hide=\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u975e\u8868\u793a\u306b\u3059\u308b
admin-console.unavailable=\u73fe\u5728\u3001\u60c5\u5831\u306f\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093
admin-console.not.installed=\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3055\u308c\u3066\u3044\u307e\u305b\u3093
admin-console.requesterror=\u30ea\u30af\u30a8\u30b9\u30c8\u3092\u5b8c\u4e86\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002

View File

@@ -20,7 +20,6 @@ admin-console.close=Lukk
admin-console.password.show=Vis passord
admin-console.password.hide=Skjul passord
admin-console.unavailable=Informasjon er for tiden ikke tilgjengelig
admin-console.not.installed=Ikke installert
admin-console.requesterror=Vi kunne ikke fullf\u00f8re foresp\u00f8rselen.

View File

@@ -20,7 +20,6 @@ admin-console.close=Sluiten
admin-console.password.show=Wachtwoord weergeven
admin-console.password.hide=Wachtwoord verbergen
admin-console.unavailable=Informatie is momenteel niet beschikbaar
admin-console.not.installed=Niet ge\u00efnstalleerd
admin-console.requesterror=Kan de aanvraag niet uitvoeren.

View File

@@ -20,7 +20,6 @@ admin-console.close=Zamknij
admin-console.password.show=Poka\u017c has\u0142o
admin-console.password.hide=Ukryj has\u0142o
admin-console.unavailable=Informacja nie jest aktualnie dost\u0119pna
admin-console.not.installed=Niezainstalowane
admin-console.requesterror=Nie mo\u017cna wykona\u0107 Twojego zapytania. Spr\u00f3buj ponownie.

View File

@@ -20,7 +20,6 @@ admin-console.close=Fechar
admin-console.password.show=Mostrar senha
admin-console.password.hide=Ocultar senha
admin-console.unavailable=Informa\u00e7\u00e3o indispon\u00edvel no momento
admin-console.not.installed=N\u00e3o instalado
admin-console.requesterror=N\u00e3o conseguimos concluir a solicita\u00e7\u00e3o.

View File

@@ -20,7 +20,6 @@ admin-console.close=\u0417\u0430\u043a\u0440\u044b\u0442\u044c
admin-console.password.show=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c
admin-console.password.hide=\u0421\u043a\u0440\u044b\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c
admin-console.unavailable=\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0441\u0435\u0439\u0447\u0430\u0441 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430
admin-console.not.installed=\u041d\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e
admin-console.requesterror=\u041d\u0430\u043c \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441.

View File

@@ -20,7 +20,6 @@ admin-console.close=St\u00e4ng
admin-console.password.show=Visa l\u00f6senord
admin-console.password.hide=D\u00f6lj l\u00f6senord
admin-console.unavailable=Informationen \u00e4r f\u00f6r n\u00e4rvarande otillg\u00e4nglig
admin-console.not.installed=Inte installerad
admin-console.requesterror=Vi kunde inte slutf\u00f6ra din beg\u00e4ran. F\u00f6rs\u00f6k igen.

View File

@@ -20,7 +20,6 @@ admin-console.close=\u5173\u95ed
admin-console.password.show=\u663e\u793a\u5bc6\u7801
admin-console.password.hide=\u9690\u85cf\u5bc6\u7801
admin-console.unavailable=\u4fe1\u606f\u5f53\u524d\u4e0d\u53ef\u7528
admin-console.not.installed=\u672a\u5b89\u88c5
admin-console.requesterror=\u6211\u4eec\u65e0\u6cd5\u5b8c\u6210\u8bf7\u6c42\u3002

View File

@@ -1,28 +1,28 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.webdav;
import static org.junit.Assert.assertEquals;
@@ -223,25 +223,6 @@ public class UnlockMethodTest
}
}
/**
* OpenOffice.org on Windows 7 results in a lock token header that is NOT enclosed in
* the required &lt; and &gt; characters. Whilst technically an invalid header, we treat
* this case specially for reasons of interoperability (ALF-13904)
*
* @throws WebDAVServerException
*/
@Test
public void parseLockTokenHeaderFromOOoOnWindows7() throws WebDAVServerException
{
String lockToken = "976e2f82-40ab-4852-a867-986e9ce11f82:admin";
// Note the missing enclosing < and > characters
String lockHeaderValue = WebDAV.OPAQUE_LOCK_TOKEN + lockToken;
request.addHeader(WebDAV.HEADER_LOCK_TOKEN, lockHeaderValue);
unlockMethod.parseRequestHeaders();
assertEquals(lockToken, unlockMethod.getLockToken());
}
/**
* Test MNT-9680: Working copies are open in read-only mode when using Webdav online edit
*

View File

@@ -321,8 +321,7 @@ public class RenditionsTest extends AbstractBaseApiTest
// renditionId in the path parameter is not registered/available
getSingle(getNodeRenditionsUrl(contentNodeId), ("renditionId" + System.currentTimeMillis()), 404);
// Create a node without any content. Test only if OpenOffice is available
if(isOpenOfficeAvailable())
if (areLocalTransformsAvailable())
{
String emptyContentNodeId = addToDocumentLibrary(userOneN1Site, "emptyDoc.txt", TYPE_CM_CONTENT, userOneN1.getId());
getSingle(getNodeRenditionsUrl(emptyContentNodeId), "doclib", 200);
@@ -410,8 +409,7 @@ public class RenditionsTest extends AbstractBaseApiTest
// Create 'doclib' rendition request
Rendition renditionRequest = new Rendition().setId("doclib");
// Test only if OpenOffice is available
if (isOpenOfficeAvailable())
if (areLocalTransformsAvailable())
{
// Create a node without any content
String emptyContentNodeId = addToDocumentLibrary(userOneN1Site, "emptyDoc.txt", TYPE_CM_CONTENT, userOneN1.getId());
@@ -557,7 +555,7 @@ public class RenditionsTest extends AbstractBaseApiTest
response = getSingle(getNodeRenditionsUrl(contentNodeId), ("doclib/content"), params, 200);
assertNotNull(response.getResponseAsBytes());
if(isOpenOfficeAvailable())
if (areLocalTransformsAvailable())
{
// Create multipart request - Word doc file
renditionName = "doclib";
@@ -963,10 +961,9 @@ public class RenditionsTest extends AbstractBaseApiTest
}
/**
* Returns <code>true</code> if OpenOffice-based transformations are currently known to
* be available, else <code>false</code>.
* Returns <code>true</code> if doc to pdf transformations available, indicating Local transforms ar available.
*/
protected boolean isOpenOfficeAvailable()
protected boolean areLocalTransformsAvailable()
{
return synchronousTransformClient.isSupported(MimetypeMap.MIMETYPE_WORD, -1, null,
MimetypeMap.MIMETYPE_PDF, Collections.emptyMap(), null, null);

View File

@@ -13,7 +13,6 @@ log4j.logger.org.alfresco.repo.content.transform.TransformerDebug=debug
log4j.logger.org.alfresco.repo.rendition2=debug
#log4j.logger.org.alfresco.repo.rendition2.LocalTransformClient=debug
#log4j.logger.org.alfresco.repo.rendition2.LegacyTransformClient=debug
#log4j.logger.org.alfresco.repo.rendition.RenditionServiceImpl=debug
#log4j.logger.org.alfresco.enterprise.repo.rendition2.RemoteTransformClient=debug
log4j.logger.org.alfresco.repo.thumbnail.ThumbnailServiceImplTest=DEBUG

View File

@@ -264,21 +264,6 @@
<groupId>org.apache.xmlbeans</groupId>
<artifactId>xmlbeans</artifactId>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>fontbox</artifactId>
<version>${dependency.pdfbox.version}</version>
</dependency>
<dependency>
<!-- we need this for TextToPdfContentTransformer -->
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox-tools</artifactId>
<version>${dependency.pdfbox.version}</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
@@ -311,16 +296,6 @@
<artifactId>FastInfoset</artifactId>
<version>1.2.18</version>
</dependency>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-jodconverter-core</artifactId>
<version>3.0.1.1</version>
</dependency>
<dependency>
<groupId>jmagick</groupId>
<artifactId>jmagick</artifactId>
<version>6.6.9</version>
</dependency>
<dependency>
<groupId>org.htmlparser</groupId>
<artifactId>htmlparser</artifactId>
@@ -335,33 +310,6 @@
<artifactId>jaxen</artifactId>
<version>1.2.0</version>
</dependency>
<!-- Apache POI -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>${dependency.poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${dependency.poi.version}</version>
<exclusions>
<exclusion>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>ooxml-schemas</artifactId>
<version>${dependency.ooxml-schemas.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>${dependency.poi.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
@@ -1048,102 +996,6 @@
</dependency>
</dependencies>
<profiles>
<!-- Profiles to extract the alfresco-pdf-renderer -->
<profile>
<id>win-alfresco-pdf-renderer-test</id>
<activation>
<os>
<family>windows</family>
</os>
</activation>
<dependencies>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-pdf-renderer</artifactId>
<classifier>win64</classifier>
<type>tgz</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<inherited>false</inherited>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>extract-alfresco-pdf-renderer-test</id>
<phase>generate-test-resources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<skip>${skipTests}</skip>
<target>
<echo message="Extracting alfresco-pdf-renderer (windows) for testing..." />
<mkdir dir="${project.build.directory}/test-binaries/alfresco-pdf-renderer" />
<untar compression="gzip" src="${settings.localRepository}/org/alfresco/alfresco-pdf-renderer/${dependency.alfresco-pdf-renderer.version}/alfresco-pdf-renderer-${dependency.alfresco-pdf-renderer.version}-win64.tgz" dest="${project.build.directory}/test-binaries/alfresco-pdf-renderer" />
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<alfresco-pdf-renderer.exe>${project.build.directory}/test-binaries/alfresco-pdf-renderer/alfresco-pdf-renderer</alfresco-pdf-renderer.exe>
</properties>
</profile>
<profile>
<id>linux-alfresco-pdf-renderer-test</id>
<activation>
<os>
<family>linux</family>
</os>
</activation>
<dependencies>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-pdf-renderer</artifactId>
<classifier>linux</classifier>
<type>tgz</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<inherited>false</inherited>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>extract-alfresco-pdf-renderer-test</id>
<phase>generate-test-resources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<skip>${skipTests}</skip>
<target>
<echo message="Extracting alfresco-pdf-renderer (linux) for testing..." />
<mkdir dir="${project.build.directory}/test-binaries/alfresco-pdf-renderer" />
<exec failonerror="true" executable="tar" dir="${project.build.directory}/test-binaries/alfresco-pdf-renderer">
<arg value="xf" />
<arg value="${settings.localRepository}/org/alfresco/alfresco-pdf-renderer/${dependency.alfresco-pdf-renderer.version}/alfresco-pdf-renderer-${dependency.alfresco-pdf-renderer.version}-linux.tgz" />
</exec>
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<alfresco-pdf-renderer.exe>${project.build.directory}/test-binaries/alfresco-pdf-renderer/alfresco-pdf-renderer</alfresco-pdf-renderer.exe>
</properties>
</profile>
</profiles>
<build>
<plugins>
<!-- Create a jar of test classes -->
@@ -1169,8 +1021,6 @@
<!-- To prevent tests alfresco.log to be created in project roots and bother while synchronizing with SCM -->
<workingDirectory>${project.build.directory}</workingDirectory>
<systemPropertyVariables>
<alfresco-pdf-renderer.exe>${alfresco-pdf-renderer.exe}</alfresco-pdf-renderer.exe>
<!-- Database related properties -->
<db.url>${db.url}</db.url>
<db.driver>${db.driver}</db.driver>
@@ -1178,7 +1028,6 @@
<db.username>${db.username}</db.username>
<db.password>${db.password}</db.password>
<dir.root>${dir.root}</dir.root>
<img.exe>${img.exe}</img.exe>
<!-- BDE-91 -->
<alfresco.rmi.services.retries>30</alfresco.rmi.services.retries>
<alfresco.rmi.services.retryInterval>2000</alfresco.rmi.services.retryInterval>

View File

@@ -80,7 +80,7 @@ import java.util.Set;
* @author Derek Hulley
* @since 3.2
*/
public class ContentServiceImpl extends ContentTransformServiceAdaptor implements ContentService, ApplicationContextAware
public class ContentServiceImpl implements ContentService, ApplicationContextAware
{
private static Log logger = LogFactory.getLog(ContentServiceImpl.class);

View File

@@ -1,311 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2019 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.content.transform.AbstractContentTransformer2;
import org.alfresco.repo.content.transform.ContentTransformer;
import org.alfresco.repo.content.transform.LocalTransform;
import org.alfresco.repo.content.transform.LocalTransformServiceRegistry;
import org.alfresco.repo.content.transform.UnsupportedTransformationException;
import org.alfresco.repo.rendition2.LegacySynchronousTransformClient;
import org.alfresco.repo.rendition2.SynchronousTransformClient;
import org.alfresco.repo.rendition2.TransformationOptionsConverter;
import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentTransformService;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NoTransformerException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.transform.client.registry.TransformServiceRegistry;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* Contains deprecated methods originally from {@link org.alfresco.repo.content.ContentServiceImpl} that is used to
* perform Legacy transforms.
*
* @author adavis
*/
@Deprecated
public class ContentTransformServiceAdaptor implements ContentTransformService
{
private ContentTransformer imageMagickContentTransformer;
private LegacySynchronousTransformClient legacySynchronousTransformClient;
private LocalTransformServiceRegistry localTransformServiceRegistryImpl;
private SynchronousTransformClient synchronousTransformClient;
private TransformServiceRegistry localTransformServiceRegistry;
private TransformationOptionsConverter converter;
@Deprecated
public void setImageMagickContentTransformer(ContentTransformer imageMagickContentTransformer)
{
this.imageMagickContentTransformer = imageMagickContentTransformer;
}
public void setLegacySynchronousTransformClient(LegacySynchronousTransformClient legacySynchronousTransformClient)
{
this.legacySynchronousTransformClient = legacySynchronousTransformClient;
}
public void setLocalTransformServiceRegistryImpl(LocalTransformServiceRegistry localTransformServiceRegistryImpl)
{
this.localTransformServiceRegistryImpl = localTransformServiceRegistryImpl;
}
public void setSynchronousTransformClient(SynchronousTransformClient synchronousTransformClient)
{
this.synchronousTransformClient = synchronousTransformClient;
}
public void setLocalTransformServiceRegistry(TransformServiceRegistry localTransformServiceRegistry)
{
this.localTransformServiceRegistry = localTransformServiceRegistry;
}
public void setConverter(TransformationOptionsConverter converter)
{
this.converter = converter;
}
@Deprecated
@Override
public void transform(ContentReader reader, ContentWriter writer)
{
synchronousTransformClient.transform(reader, writer, Collections.emptyMap(), null, null);
}
@Deprecated
@Override
public void transform(ContentReader reader, ContentWriter writer, Map<String, Object> legacyOptionsMap)
throws NoTransformerException, ContentIOException
{
TransformationOptions transformationOptions = new TransformationOptions(legacyOptionsMap);
Map<String, String> options = converter.getOptions(transformationOptions, null, null);
synchronousTransformClient.transform(reader, writer, options, null, null);
}
@Deprecated
@Override
public void transform(ContentReader reader, ContentWriter writer, TransformationOptions transformationOptions)
throws NoTransformerException, ContentIOException
{
try
{
Map<String, String> options = converter.getOptions(transformationOptions, null, null);
synchronousTransformClient.transform(reader, writer, options, null, null);
}
catch (UnsupportedTransformationException ute)
{
throw newNoTransformerException(reader, writer);
}
catch (IllegalArgumentException iae)
{
if (iae.getMessage().contains("sourceNodeRef null has no content"))
{
throw newNoTransformerException(reader, writer);
}
throw new AlfrescoRuntimeException(iae.getMessage(), iae);
}
}
private NoTransformerException newNoTransformerException(ContentReader reader, ContentWriter writer)
{
String sourceMimetype = reader == null ? "null" : reader.getMimetype();
String targetMimetype = writer == null ? "null" : writer.getMimetype();
return new NoTransformerException(sourceMimetype, targetMimetype);
}
@Deprecated
@Override
public ContentTransformer getTransformer(String sourceMimetype, String targetMimetype)
{
return getTransformer(sourceMimetype, targetMimetype, new TransformationOptions());
}
@Deprecated
@Override
public ContentTransformer getTransformer(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
return getTransformer(null, sourceMimetype, -1, targetMimetype, new TransformationOptions());
}
@Deprecated
@Override
public ContentTransformer getTransformer(String sourceUrl, String sourceMimetype, long sourceSize,
String targetMimetype, TransformationOptions options)
{
ContentTransformer localTransformer = wrapLocalTransformer(sourceUrl, sourceMimetype, sourceSize, targetMimetype, options);
return localTransformer == null
? legacySynchronousTransformClient.getTransformer(sourceUrl, sourceMimetype, sourceSize, targetMimetype, options)
: localTransformer;
}
@Deprecated
@Override
// Same as getActiveTransformers, but with debug
public List<ContentTransformer> getTransformers(String sourceUrl, String sourceMimetype, long sourceSize,
String targetMimetype, TransformationOptions options)
{
ContentTransformer localTransformer = wrapLocalTransformer(sourceUrl, sourceMimetype, sourceSize, targetMimetype, options);
return localTransformer == null
? legacySynchronousTransformClient.getTransformers(sourceUrl, sourceMimetype, sourceSize, targetMimetype, options)
: Collections.singletonList(localTransformer);
}
@Deprecated
@Override
// Same as getTransformers, but without debug
public List<ContentTransformer> getActiveTransformers(String sourceMimetype,
String targetMimetype, TransformationOptions options)
{
return getActiveTransformers(sourceMimetype, -1, targetMimetype, options);
}
@Deprecated
@Override
// Same as getTransformers, but without debug
public List<ContentTransformer> getActiveTransformers(String sourceMimetype, long sourceSize,
String targetMimetype, TransformationOptions options)
{
ContentTransformer localTransformer = wrapLocalTransformer(null, sourceMimetype, sourceSize, targetMimetype, options);
return localTransformer == null
? legacySynchronousTransformClient.getActiveTransformers(sourceMimetype, sourceSize, targetMimetype, options)
: Collections.singletonList(localTransformer);
}
private ContentTransformer wrapLocalTransformer(String sourceUrl, String sourceMimetype, long sourceSize,
String targetMimetype, TransformationOptions transformationOptions)
{
AbstractContentTransformer2 transformer = null;
Map<String, String> options = converter.getOptions(transformationOptions, null, null);
LocalTransform localTransform = localTransformServiceRegistryImpl.getLocalTransform(sourceMimetype,
sourceSize, targetMimetype, options, null);
if (localTransform != null)
{
transformer = new AbstractContentTransformer2() {
@Override
public void transform(ContentReader reader, ContentWriter writer, TransformationOptions options)
throws ContentIOException
{
try
{
transformInternal(reader, writer, transformationOptions);
}
catch (Exception e)
{
throw new ContentIOException(e.getMessage(), e);
}
}
@Override
protected void transformInternal(ContentReader reader, ContentWriter writer, TransformationOptions transformationOptions) throws Exception
{
localTransform.transform(reader, writer, options, null, null);
}
@Override
public void register()
{
}
@Override
public boolean isSupportedTransformation(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
return true;
}
@Override
public boolean isTransformable(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options)
{
return true;
}
@Override
public boolean isTransformableMimetype(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
return true;
}
@Override
public boolean isTransformableSize(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options)
{
return true;
}
@Override
public String getName()
{
return "Wrapped<"+localTransformServiceRegistryImpl.findTransformerName(sourceMimetype, sourceSize,
targetMimetype, options, null)+">";
}
};
}
return transformer;
}
@Deprecated
@Override
public long getMaxSourceSizeBytes(String sourceMimetype,
String targetMimetype, TransformationOptions transformationOptions)
{
Map<String, String> options = converter.getOptions(transformationOptions, null, null);
return localTransformServiceRegistry.findMaxSize(sourceMimetype, targetMimetype, options, null);
}
@Deprecated
@Override
public ContentTransformer getImageTransformer()
{
return imageMagickContentTransformer;
}
@Deprecated
@Override
public boolean isTransformable(ContentReader reader, ContentWriter writer)
{
return isTransformable(reader, writer, null);
}
@Deprecated
@Override
public boolean isTransformable(ContentReader reader, ContentWriter writer, TransformationOptions transformationOptions)
{
String sourceMimetype = reader.getMimetype();
long sourceSizeInBytes = reader.getSize();
String contentUrl = reader.getContentUrl();
String targetMimetype = writer.getMimetype();
NodeRef sourceNodeRef = transformationOptions.getSourceNodeRef();
Map<String, String> options = converter.getOptions(transformationOptions, null, null);
return synchronousTransformClient.isSupported(sourceMimetype, sourceSizeInBytes, contentUrl, targetMimetype,
options, null, sourceNodeRef);
}
}

View File

@@ -1,45 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2017 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content;
import org.artofsolving.jodconverter.office.OfficeManager;
///////// THIS FILE IS A COPY OF THE CODE IN alfresco-docker-libreoffice /////////////
public interface JodConverter
{
/**
* Gets the JodConverter OfficeManager.
* @return
*/
public abstract OfficeManager getOfficeManager();
/**
* This method returns a boolean indicating whether the JodConverter connection to OOo is available.
* @return <code>true</code> if available, else <code>false</code>
*/
public abstract boolean isAvailable();
}

View File

@@ -1,537 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content;
import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import org.alfresco.error.AlfrescoRuntimeException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.artofsolving.jodconverter.office.DefaultOfficeManagerConfiguration;
import org.artofsolving.jodconverter.office.OfficeException;
import org.artofsolving.jodconverter.office.OfficeManager;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
///////// THIS FILE IS A COPY OF THE CODE IN alfresco-docker-libreoffice /////////////
/**
* Makes use of the JodConverter library and an installed
* OpenOffice application to perform OpenOffice-driven conversions.
*
* @author Neil McErlean
*/
public class JodConverterSharedInstance implements InitializingBean, DisposableBean, JodConverter
{
private static Log logger = LogFactory.getLog(JodConverterSharedInstance.class);
private OfficeManager officeManager;
boolean isAvailable = false;
// JodConverter's built-in configuration settings.
//
// These properties are set by Spring dependency injection at system startup in the usual way.
// If the values are changed via the JMX console at runtime, then the subsystem will be stopped
// and can be restarted with the new values - meaning that JodConverter will also be stopped and restarted.
// Therefore there is no special handling required for changes to e.g. portNumbers which determines
// the number of OOo instances there should be in the pool.
//
// Numeric parameters have to be handled as Strings, as that is what Spring gives us for missing values
// e.g. if jodconverter.maxTasksPerProcess is not specified in the properties file, the value
// "${jodconverter.maxTasksPerProcess}" will be injected.
private Integer maxTasksPerProcess;
private String url;
private String officeHome;
private int[] portNumbers;
private Long taskExecutionTimeout;
private Long taskQueueTimeout;
private File templateProfileDir;
private Boolean enabled;
private Long connectTimeout;
private String deprecatedOooExe;
private Boolean deprecatedOooEnabled;
private int[] deprecatedOooPortNumbers;
public void setMaxTasksPerProcess(String maxTasksPerProcess)
{
Long l = parseStringForLong(maxTasksPerProcess.trim());
if (l != null)
{
this.maxTasksPerProcess = l.intValue();
}
}
public void setUrl(String url)
{
this.url = url == null ? null : url.trim();
}
public void setOfficeHome(String officeHome)
{
this.officeHome = officeHome == null ? "" : officeHome.trim();
}
public void setDeprecatedOooExe(String deprecatedOooExe)
{
this.deprecatedOooExe = deprecatedOooExe == null ? "" : deprecatedOooExe.trim();
}
public void setPortNumbers(String s)
{
portNumbers = parsePortNumbers(s, "jodconverter");
}
public void setDeprecatedOooPort(String s)
{
deprecatedOooPortNumbers = parsePortNumbers(s, "ooo");
}
private int[] parsePortNumbers(String s, String sys)
{
int[] portNumbers = null;
s = s == null ? null : s.trim();
if (s != null && !s.isEmpty())
{
StringTokenizer tokenizer = new StringTokenizer(s, ",");
int tokenCount = tokenizer.countTokens();
portNumbers = new int[tokenCount];
for (int i = 0;tokenizer.hasMoreTokens();i++)
{
try
{
portNumbers[i] = Integer.parseInt(tokenizer.nextToken().trim());
}
catch (NumberFormatException e)
{
// Logging this as an error as this property would prevent JodConverter & therefore
// OOo from starting as specified
if (logger.isErrorEnabled())
{
logger.error("Unparseable value for property '" + sys + ".portNumbers': " + s);
}
// We'll not rethrow the exception, instead allowing the problem to be picked up
// when the OOoJodConverter subsystem is started.
}
}
}
return portNumbers;
}
public void setTaskExecutionTimeout(String taskExecutionTimeout)
{
this.taskExecutionTimeout = parseStringForLong(taskExecutionTimeout.trim());
}
public void setTemplateProfileDir(String templateProfileDir)
{
if (templateProfileDir == null || templateProfileDir.trim().length() == 0)
{
this.templateProfileDir = null;
}
else
{
File tmp = new File(templateProfileDir);
if (!tmp.isDirectory())
{
throw new AlfrescoRuntimeException("OpenOffice template profile directory "+templateProfileDir+" does not exist.");
}
this.templateProfileDir = tmp;
}
}
public void setTaskQueueTimeout(String taskQueueTimeout)
{
this.taskQueueTimeout = parseStringForLong(taskQueueTimeout.trim());
}
public void setConnectTimeout(String connectTimeout)
{
this.connectTimeout = parseStringForLong(connectTimeout.trim());
}
public void setEnabled(String enabled)
{
this.enabled = parseEnabled(enabled);
// If this is a request from the Enterprise Admin console to disable the JodConverter.
if (this.enabled == false && (deprecatedOooEnabled == null || deprecatedOooEnabled == false))
{
// We need to change isAvailable to false so we don't make calls to a previously started OfficeManger.
// In the case of Enterprise it is very unlikely that ooo.enabled will have been set to true.
this.isAvailable = false;
}
}
public void setDeprecatedOooEnabled(String deprecatedOooEnabled)
{
this.deprecatedOooEnabled = parseEnabled(deprecatedOooEnabled);
// No need to worry about isAvailable as this setting cannot be changed via the Admin console.
}
private Boolean parseEnabled(String enabled)
{
enabled = enabled == null ? "" : enabled.trim();
return Boolean.parseBoolean(enabled);
}
// So that Community systems <= Alfresco 6.0.1-ea keep working on upgrade, we may need to use the deprecated
// ooo.exe setting rather than the jodconverter.officeHome setting if we don't have the jod setting as
// oooDirect was replaced by jodconverter after this release.
String getOfficeHome()
{
String officeHome = this.officeHome;
if ((officeHome == null || officeHome.isEmpty()) && (deprecatedOooExe != null && !deprecatedOooExe.isEmpty()))
{
// It will only be possible to use the ooo.exe value if it includes a path, which itself has the officeHome
// value in it.
// jodconverter.officeHome=/opt/libreoffice5.4/
// ooo.exe=/opt/libreoffice5.4/program/soffice.bin
// jodconverter.officeHome=C:/noscan/installs/521~1.1/LIBREO~1/App/libreoffice
// ooo.exe=C:/noscan/installs/COMMUN~1.0-E/LIBREO~1/App/libreoffice/program/soffice.exe
File oooExe = new File(deprecatedOooExe);
File parent = oooExe.getParentFile();
if (parent != null && "program".equals(parent.getName()))
{
File grandparent = parent.getParentFile();
if (grandparent != null)
{
officeHome = grandparent.getPath();
}
}
}
return officeHome;
}
// So that Community systems <= Alfresco 6.0.1-ea keep working on upgrade, we may need to use the deprecated
// ooo.enabled setting if true rather than the jodconverter.enabled setting as oooDirect was replaced by
// jodconverter after this release.
// If ooo.enabled is true the JodConverter will be enabled.
// If ooo.enabled is false or unset the jodconverter.enabled value is used.
// Community set properties via alfresco-global.properties.
// Enterprise may do the same but may also reset jodconverter.enabled them via the Admin console.
// In the case of Enterprise it is very unlikely that ooo.enabled will be set to true.
boolean isEnabled()
{
return (deprecatedOooEnabled != null && deprecatedOooEnabled) || (enabled != null && enabled);
}
// So that Community systems <= Alfresco 6.0.1-ea keep working on upgrade, we may need to use the deprecated
// ooo.port setting rather than the jodconverter.portNumbers if ooo.enabled is true and jodconverter.enabled
// is false.
int[] getPortNumbers()
{
return (enabled == null || !enabled) && deprecatedOooEnabled != null && deprecatedOooEnabled
? deprecatedOooPortNumbers
: portNumbers;
}
private Long parseStringForLong(String string)
{
Long result = null;
try
{
long l = Long.parseLong(string);
result = new Long(l);
}
catch (NumberFormatException nfe)
{
if (logger.isDebugEnabled())
{
logger.debug("Cannot parse numerical value from " + string);
}
// else intentionally empty
}
return result;
}
/*
* (non-Javadoc)
* @see org.alfresco.repo.content.JodConverter#isAvailable()
*/
public boolean isAvailable()
{
final boolean result = isAvailable && (officeManager != null || (url != null && !url.isEmpty()));
return result;
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
public void afterPropertiesSet() throws Exception
{
// isAvailable defaults to false afterPropertiesSet. It only becomes true on successful completion of this method.
this.isAvailable = false;
int[] portNumbers = getPortNumbers();
String officeHome = getOfficeHome();
if (logger.isDebugEnabled())
{
logger.debug("JodConverter settings (null settings will be replaced by jodconverter defaults):");
logger.debug(" officeHome = " + officeHome);
logger.debug(" enabled = " + isEnabled());
logger.debug(" portNumbers = " + getString(portNumbers));
logger.debug(" ooo.exe = " + deprecatedOooExe);
logger.debug(" ooo.enabled = " + deprecatedOooEnabled);
logger.debug(" ooo.port = " + getString(deprecatedOooPortNumbers));
logger.debug(" jodConverter.enabled = " + enabled);
logger.debug(" jodconverter.portNumbers = " + getString(this.portNumbers));
logger.debug(" jodconverter.officeHome = " + this.officeHome);
logger.debug(" jodconverter.maxTasksPerProcess = " + maxTasksPerProcess);
logger.debug(" jodconverter.taskExecutionTimeout = " + taskExecutionTimeout);
logger.debug(" jodconverter.taskQueueTimeout = " + taskQueueTimeout);
logger.debug(" jodconverter.connectTimeout = " + connectTimeout);
logger.debug(" jodconverter.url = " + url);
}
// Only start the JodConverter instance(s) if the subsystem is enabled.
if (isEnabled() == false)
{
return;
}
if (url == null || url.isEmpty())
{
logAllSofficeFilesUnderOfficeHome();
try
{
DefaultOfficeManagerConfiguration defaultOfficeMgrConfig = new DefaultOfficeManagerConfiguration();
if (maxTasksPerProcess != null && maxTasksPerProcess > 0)
{
defaultOfficeMgrConfig.setMaxTasksPerProcess(maxTasksPerProcess);
}
if (officeHome != null && officeHome.length() != 0)
{
defaultOfficeMgrConfig.setOfficeHome(officeHome);
}
if (portNumbers != null && portNumbers.length != 0)
{
defaultOfficeMgrConfig.setPortNumbers(portNumbers);
}
if (taskExecutionTimeout != null && taskExecutionTimeout > 0)
{
defaultOfficeMgrConfig.setTaskExecutionTimeout(taskExecutionTimeout);
}
if (taskQueueTimeout != null && taskQueueTimeout > 0)
{
defaultOfficeMgrConfig.setTaskQueueTimeout(taskQueueTimeout);
}
if (templateProfileDir != null)
{
defaultOfficeMgrConfig.setTemplateProfileDir(templateProfileDir);
}
if (connectTimeout != null)
{
defaultOfficeMgrConfig.setConnectTimeout(connectTimeout);
}
// Try to configure and start the JodConverter library.
officeManager = defaultOfficeMgrConfig.buildOfficeManager();
officeManager.start();
}
catch (IllegalStateException isx)
{
if (logger.isErrorEnabled())
{
logger.error("Unable to pre-initialise JodConverter library. "
+ "The following error is shown for informational purposes only.", isx);
}
return;
}
catch (OfficeException ox)
{
if (logger.isErrorEnabled())
{
logger.error("Unable to start JodConverter library. "
+ "The following error is shown for informational purposes only.", ox);
}
// We need to let it continue (comment-out return statement) even if an error occurs. See MNT-13706 and associated issues.
//return;
}
catch (Exception x)
{
if (logger.isErrorEnabled())
{
logger.error("Unexpected error in configuring or starting the JodConverter library."
+ "The following error is shown for informational purposes only.", x);
}
return;
}
}
// If any exceptions are thrown in the above code, then isAvailable
// should remain false, hence the return statements.
this.isAvailable = true;
}
private String getString(int[] portNumbers)
{
StringBuilder portInfo = new StringBuilder();
if (portNumbers != null)
{
for (int i = 0;i < portNumbers.length;i++)
{
portInfo.append(portNumbers[i]);
if (i < portNumbers.length - 1)
{
portInfo.append(", ");
}
}
}
return portInfo.toString();
}
private void logAllSofficeFilesUnderOfficeHome()
{
if (logger.isDebugEnabled() == false)
{
return;
}
String officeHome = getOfficeHome();
File requestedOfficeHome = new File(officeHome);
logger.debug("Some information on soffice* files and their permissions");
logFileInfo(requestedOfficeHome);
for (File f : findSofficePrograms(requestedOfficeHome, new ArrayList<File>(), 2))
{
logFileInfo(f);
}
}
private List<File> findSofficePrograms(File searchRoot, List<File> results, int maxRecursionDepth)
{
return this.findSofficePrograms(searchRoot, results, 0, maxRecursionDepth);
}
private List<File> findSofficePrograms(File searchRoot, List<File> results,
int currentRecursionDepth, int maxRecursionDepth)
{
if (currentRecursionDepth >= maxRecursionDepth)
{
return results;
}
File[] matchingFiles = searchRoot.listFiles(new FilenameFilter()
{
@Override
public boolean accept(File dir, String name)
{
return name.startsWith("soffice");
}
});
for (File f : matchingFiles)
{
results.add(f);
}
for (File dir : searchRoot.listFiles(new FileFilter()
{
@Override
public boolean accept(File f) {
return f.isDirectory();
}
}))
{
findSofficePrograms(dir, results, currentRecursionDepth + 1, maxRecursionDepth);
}
return results;
}
/**
* Logs some information on the specified file, including name and r/w/x permissions.
* @param f the file to log.
*/
private void logFileInfo(File f)
{
if (logger.isDebugEnabled() == false)
{
return;
}
StringBuilder msg = new StringBuilder();
msg.append(f).append(" ");
if (f.exists())
{
if (f.canRead())
{
msg.append("(")
.append(f.isDirectory() ? "d" : "-")
.append(f.canRead() ? "r" : "-")
.append(f.canWrite() ? "w" : "-")
.append(f.canExecute() ? "x" : "-")
.append(")");
}
}
else
{
msg.append("does not exist");
}
logger.debug(msg.toString());
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.DisposableBean#destroy()
*/
public void destroy() throws Exception {
this.isAvailable = false;
if (officeManager != null)
{
// If there is an OfficeException when stopping the officeManager below, then there is
// little that can be done other than logging the exception and carrying on. The JodConverter-based
// libraries will not be used in any case, as isAvailable is false.
//
// Any exception thrown out of this method will be logged and swallowed by Spring
// (see javadoc for method declaration). Therefore there is no handling here for
// exceptions from jodConverter.
officeManager.stop();
}
}
/* (non-Javadoc)
* @see org.alfresco.repo.content.JodConverterWorker#getOfficeManager()
*/
public OfficeManager getOfficeManager()
{
return officeManager;
}
}

View File

@@ -1,117 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content;
import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
import java.util.HashSet;
import java.util.Set;
import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.util.IOUtils;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MediaType;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.Parser;
import org.apache.tika.parser.microsoft.OfficeParser;
import org.apache.tika.parser.microsoft.ooxml.OOXMLParser;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
///////// THIS FILE IS A COPY OF THE CODE IN alfresco-docker-tika /////////////
/**
* <a href="http://tika.apache.org/Apache Tika">Apache Tika</a> assumes that
* you either know exactly what your content is, or that
* you'll leave it to auto-detection.
* Within Alfresco, we usually do know. However, from time
* to time, we don't know if we have one of the old or one
* of the new office files (eg .xls and .xlsx).
* This class allows automatically selects the appropriate
* old (OLE2) or new (OOXML) Tika parser as required.
*
* @author Nick Burch
*/
public class TikaOfficeDetectParser implements Parser {
private Parser ole2Parser = new OfficeParser();
private Parser ooxmlParser = new OOXMLParser();
public Set<MediaType> getSupportedTypes(ParseContext parseContext) {
Set<MediaType> types = new HashSet<MediaType>();
types.addAll(ole2Parser.getSupportedTypes(parseContext));
types.addAll(ooxmlParser.getSupportedTypes(parseContext));
return types;
}
public void parse(InputStream stream,
ContentHandler handler, Metadata metadata,
ParseContext parseContext) throws IOException, SAXException,
TikaException
{
byte[] initial4 = new byte[4];
InputStream wrapped;
// Preserve TikaInputStreams as TikaInputStreams as they require less memory to process
if (stream.markSupported())
{
stream.mark(initial4.length);
IOUtils.readFully(stream, initial4);
stream.reset();
wrapped = stream;
}
else
{
PushbackInputStream inp = new PushbackInputStream(stream, 4);
IOUtils.readFully(inp, initial4);
inp.unread(initial4);
wrapped = inp;
}
// Which is it?
if(initial4[0] == POIFSConstants.OOXML_FILE_HEADER[0] &&
initial4[1] == POIFSConstants.OOXML_FILE_HEADER[1] &&
initial4[2] == POIFSConstants.OOXML_FILE_HEADER[2] &&
initial4[3] == POIFSConstants.OOXML_FILE_HEADER[3])
{
ooxmlParser.parse(wrapped, handler, metadata, parseContext);
}
else
{
ole2Parser.parse(wrapped, handler, metadata, parseContext);
}
}
/**
* @deprecated This method will be removed in Apache Tika 1.0.
*/
public void parse(InputStream stream,
ContentHandler handler, Metadata metadata)
throws IOException, SAXException, TikaException
{
parse(stream, handler, metadata, new ParseContext());
}
}

View File

@@ -1,61 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.metadata;
import java.util.List;
import org.apache.tika.extractor.DocumentSelector;
import org.apache.tika.metadata.Metadata;
/**
* @deprecated OOTB extractors are being moved to T-Engines.
*
* Tika 1.6 has the ability to parse embedded artifacts, such as images in a PDF,
* but this can be very resource intensive so adding this selector
* to parsers and transformers that handle formats with embedded artifacts
* will disable parsing of the specified content types.
*/
@Deprecated
public class MediaTypeDisablingDocumentSelector implements DocumentSelector
{
private List<String> disabledMediaTypes;
public void setDisabledMediaTypes(List<String> disabledMediaTypes)
{
this.disabledMediaTypes = disabledMediaTypes;
}
@Override
public boolean select(Metadata metadata)
{
String contentType = metadata.get(Metadata.CONTENT_TYPE);
if (contentType == null || contentType.equals("") || disabledMediaTypes == null)
{
return true;
}
return !disabledMediaTypes.contains(contentType);
}
}

View File

@@ -1,506 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.cmr.repository.ContentAccessor;
import org.alfresco.service.cmr.repository.ContentIOException;
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;
/**
* Provides basic services for {@link org.alfresco.repo.content.transform.ContentTransformer}
* implementations.
* <p>
* This class maintains the performance measures for the transformers as well, making sure that
* there is an extra penalty for transformers that fail regularly.
*
* @deprecated
* Deprecated since 3.0. The abstract base class org.alfresco.repo.content.transform.AbstractContentTransformer2 should now be used instead.
*
* @author Derek Hulley
*/
@Deprecated
public abstract class AbstractContentTransformer implements ContentTransformer, BeanNameAware
{
private static final Log logger = LogFactory.getLog(AbstractContentTransformer.class);
private MimetypeService mimetypeService;
private ContentTransformerRegistry registry;
@SuppressWarnings("deprecation")
private List<ContentTransformerRegistry.TransformationKey> explicitTransformations;
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.
*/
@SuppressWarnings("deprecation")
protected AbstractContentTransformer()
{
averageTime = 0.0;
explicitTransformations = new ArrayList<ContentTransformerRegistry.TransformationKey>(0);
}
/**
* The registry to auto-register with
*
* @param registry the transformer registry
*/
public void setRegistry(ContentTransformerRegistry registry)
{
this.registry = registry;
}
/**
* Helper setter of the mimetype service. This is not always required.
*
* @param mimetypeService MimetypeService
*/
public void setMimetypeService(MimetypeService mimetypeService)
{
this.mimetypeService = mimetypeService;
}
/**
* @return Returns the mimetype helper
*/
protected MimetypeService getMimetypeService()
{
return mimetypeService;
}
/**
* @return Returns the explicit transformations that were enabled for this transformer
*/
@SuppressWarnings("deprecation")
protected List<ContentTransformerRegistry.TransformationKey> getExplicitTransformations()
{
return explicitTransformations;
}
/**
* Set the transformations that this transformer can do regardless of what it returns
* via the reliability check.
*
* @param explicitTransformations explicit key mappings
*/
@SuppressWarnings("deprecation")
public void setExplicitTransformations(List<ContentTransformerRegistry.TransformationKey> explicitTransformations)
{
this.explicitTransformations = explicitTransformations;
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append(this.getClass().getSimpleName())
.append("[ average=").append((long)averageTime).append("ms")
.append("]");
return sb.toString();
}
/**
* Registers this instance with the {@link #setRegistry(ContentTransformerRegistry) registry}
* if it is present.
*/
public void register()
{
if (registry == null)
{
logger.warn("Property 'registry' has not been set. Ignoring auto-registration: \n" +
" transformer: " + this);
return;
}
// first register any explicit transformations
//if (explicitTransformations != null)
//{
// for (ContentTransformerRegistry.TransformationKey key : explicitTransformations)
// / {
// registry.addExplicitTransformer(key, this);
// }
//}
// register this instance for the fallback case
registry.addTransformer(this);
}
/**
* Convenience to fetch and check the mimetype for the given content
*
* @param content the reader/writer for the content
* @return Returns the mimetype for the content
* @throws AlfrescoRuntimeException if the content doesn't have a mimetype
*/
protected String getMimetype(ContentAccessor content)
{
String mimetype = content.getMimetype();
if (mimetype == null)
{
throw new AlfrescoRuntimeException("Mimetype is mandatory for transformation: " + content);
}
// done
return mimetype;
}
/**
* Added for backward compatibility of existing content transformers
*
* @param sourceMimetype the source mimetype
* @param targetMimetype the target mimetype
* @return double the reliability value of the content transformer ranging from 0 to 1
*/
protected abstract double getReliability(String sourceMimetype, String targetMimetype);
/**
* Convenience method to check the reliability of a transformation
*
* @param reader ContentReader
* @param writer ContentWriter
* @throws AlfrescoRuntimeException if the reliability isn't > 0
*/
protected void checkReliability(ContentReader reader, ContentWriter writer)
{
String sourceMimetype = getMimetype(reader);
String targetMimetype = getMimetype(writer);
double reliability = getReliability(sourceMimetype, targetMimetype);
if (reliability <= 0.0)
{
throw new AlfrescoRuntimeException("Zero scoring transformation attempted: \n" +
" reader: " + reader + "\n" +
" writer: " + writer);
}
// it all checks out OK
}
/**
* {@inheritDoc}<p>
*
* Implementation calls the deprecated overloaded method without the sourceSize parameter.
* Note: source size checked has not been added to this deprecated class.
*/
@Override
public boolean isTransformable(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options)
{
return
isTransformableMimetype(sourceMimetype, targetMimetype, options) &&
isTransformableSize(sourceMimetype, sourceSize, targetMimetype, options);
}
/**
* @deprecated use version with extra sourceSize parameter.
*/
public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
ParameterCheck.mandatoryString("sourceMimetype", sourceMimetype);
ParameterCheck.mandatoryString("targetMimetype", targetMimetype);
double reliability = getReliability(sourceMimetype, targetMimetype);
boolean result = true;
if (reliability <= 0.0)
{
result = false;
}
return result;
}
/**
* Checks the supplied mimetypes are supported by calling the deprecated
* {@link #isTransformable(String, String, TransformationOptions)} method.
*/
@Override
public boolean isTransformableMimetype(String sourceMimetype, String targetMimetype,
TransformationOptions options)
{
return isTransformable(sourceMimetype, targetMimetype, options);
}
/**
* Always returns {@code true} to indicate size is not an issue.
*/
@Override
public boolean isTransformableSize(String sourceMimetype, long sourceSize,
String targetMimetype, TransformationOptions options)
{
return true;
}
/**
* Always returns {@code -1} to indicate an unlimited size.
*/
@Override
public long getMaxSourceSizeKBytes(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
return -1;
}
/**
* @see org.alfresco.repo.content.transform.ContentTransformer#isTransformable(java.lang.String, java.lang.String, org.alfresco.service.cmr.repository.TransformationOptions)
*/
@SuppressWarnings("deprecation")
public boolean isExplicitTransformation(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
boolean result = false;
if (this.explicitTransformations != null)
{
for (ContentTransformerRegistry.TransformationKey transformationKey : this.explicitTransformations)
{
if (transformationKey.getSourceMimetype().equals(sourceMimetype) == true &&
transformationKey.getTargetMimetype().equals(targetMimetype) == true)
{
result = true;
break;
}
}
}
return result;
}
/**
* Method to be implemented by subclasses wishing to make use of the common infrastructural code
* provided by this class.
*
* @param reader the source of the content to transform
* @param writer the target to which to write the transformed content
* @param options a map of options to use when performing the transformation. The map
* will never be null.
* @throws Exception exceptions will be handled by this class - subclasses can throw anything
*/
protected abstract void transformInternal(
ContentReader reader,
ContentWriter writer,
Map<String, Object> options) throws Exception;
/**
* @see #transform(ContentReader, ContentWriter, Map)
* @see #transformInternal(ContentReader, ContentWriter, Map)
*/
public final void transform(ContentReader reader, ContentWriter writer) throws ContentIOException
{
Map<String, Object> optionsMap = null;
transform(reader, writer, optionsMap);
}
/**
* @see org.alfresco.repo.content.transform.ContentTransformer#transform(org.alfresco.service.cmr.repository.ContentReader, org.alfresco.service.cmr.repository.ContentWriter, org.alfresco.service.cmr.repository.TransformationOptions)
*/
public final void transform(ContentReader reader, ContentWriter writer, TransformationOptions options)
throws ContentIOException
{
Map<String, Object> optionsMap = options.toMap();
transform(reader, writer, optionsMap);
}
/**
* Performs the following:
* <ul>
* <li>Times the transformation</li>
* <li>Ensures that the transformation is allowed</li>
* <li>Calls the subclass implementation of {@link #transformInternal(ContentReader, ContentWriter, Map)}</li>
* <li>Transforms any exceptions generated</li>
* <li>Logs a successful transformation</li>
* </ul>
* Subclass need only be concerned with performing the transformation.
* <p>
* If the options provided are null, then an empty map will be created.
*/
@SuppressWarnings("deprecation")
public final void transform(
ContentReader reader,
ContentWriter writer,
Map<String, Object> options) throws ContentIOException
{
// begin timing
long before = System.currentTimeMillis();
// check options map
if (options == null)
{
options = Collections.emptyMap();
}
try
{
// Check the reliability
checkReliability(reader, writer);
// Transform
transformInternal(reader, writer, options);
}
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(10000); // 10 seconds, i.e. rubbish
throw new ContentIOException("Content conversion failed: \n" +
" reader: " + reader + "\n" +
" writer: " + writer + "\n" +
" options: " + options,
e);
}
finally
{
// 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);
}
}
/**
* @return Returns the calculated running average of the current transformations
*/
public synchronized long getTransformationTime()
{
return (long) averageTime;
}
public long getTransformationTime(String sourceMimetype, String targetMimetype)
{
return (long) averageTime;
}
/**
* Records and updates the average transformation time for this transformer.
* <p>
* Subclasses should call this after every transformation in order to keep
* the running average of the transformation times up to date.
* <p>
* This method is thread-safe. The time spent in this method is negligible
* so the impact will be minor.
*
* @param transformationTime the time it took to perform the transformation.
* The value may be 0.
*/
protected final 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;
}
/**
* 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;
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((beanName == null) ? 0 : beanName.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
AbstractContentTransformer other = (AbstractContentTransformer) obj;
if (beanName == null)
{
if (other.beanName != null)
return false;
}
else if (!beanName.equals(other.beanName))
return false;
return true;
}
}

View File

@@ -1,669 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.alfresco.api.AlfrescoPublicApi;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.content.AbstractStreamAwareProxy;
import org.alfresco.repo.content.StreamAwareContentReaderProxy;
import org.alfresco.repo.content.StreamAwareContentWriterProxy;
import org.alfresco.repo.content.metadata.AbstractMappingMetadataExtracter;
import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentServiceTransientException;
import org.alfresco.service.cmr.repository.ContentWriter;
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;
/**
* Provides basic services for {@link org.alfresco.repo.content.transform.ContentTransformer}
* implementations.
* <p>
* This class maintains the performance measures for the transformers as well, making sure that
* there is an extra penalty for transformers that fail regularly.
*
* @author Derek Hulley
* @author Roy Wetherall
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
@AlfrescoPublicApi
public abstract class AbstractContentTransformer2 extends AbstractContentTransformerLimits
{
private static final Log logger = LogFactory.getLog(AbstractContentTransformer2.class);
private ExecutorService executorService;
private ContentTransformerRegistry registry;
private boolean registerTransformer;
private boolean retryTransformOnDifferentMimeType;
private boolean strictMimeTypeCheck;
/**
* A flag that indicates that the transformer should be started in it own Thread so
* that it may be interrupted rather than using the timeout in the Reader.
* Need only be set for transformers that read their source data quickly but then
* take a long time to process the data (such as {@link PoiOOXMLContentTransformer}.
*/
private Boolean useTimeoutThread = false;
/**
* Extra time added the timeout when using a Thread for the transformation so that
* a timeout from the Reader has a chance to happen first.
*/
private long additionalThreadTimout = 2000;
private static ThreadLocal<Integer> depth = new ThreadLocal<Integer>()
{
@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 <beanName>.time}.
* May also be set for given combinations of source and target mimetypes.
*/
protected AbstractContentTransformer2()
{
}
/**
* The registry to auto-register with
*
* @param registry the transformer registry
*/
public void setRegistry(ContentTransformerRegistry registry)
{
this.registry = registry;
}
/**
* @param registerTransformer as been available for selection.
* If {@code false} this indicates that the transformer may only be
* used as part of another transformer.
*/
public void setRegisterTransformer(boolean registerTransformer)
{
this.registerTransformer = registerTransformer;
}
@Override
public String toString()
{
return this.getClass().getSimpleName();
}
/**
* Registers this instance with the {@link #setRegistry(ContentTransformerRegistry) registry}
* if it is present.
*
* 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" +
" transformer: " + this.getName());
}
else if (registerTransformer)
{
registry.addTransformer(this);
}
else
{
registry.addComponentTransformer(this);
logger.debug("Property 'registerTransformer' have not been set, so transformer (" +
this.getName() + ") may only be used as a component of a complex transformer.");
}
}
/**
* Convenience method to check the transformability of a transformation
*
* @param reader content reader
* @param writer content writer
* @param options transformation options
* @throws AlfrescoRuntimeException if the the transformation isn't supported
*/
protected void checkTransformable(ContentReader reader, ContentWriter writer, TransformationOptions options)
{
String sourceMimetype = getMimetype(reader);
String targetMimetype = getMimetype(writer);
long sourceSize = reader.getSize();
boolean transformable = isTransformable(sourceMimetype, sourceSize, targetMimetype, options);
if (transformable == false)
{
// This method is only called once a transformer has been selected, so it should be able to
// handle the mimetypes but might not be able to handle all the limits as it might be part of
// of a complex (compound) transformer. So report the max size if set.
long maxSourceSizeKBytes = getMaxSourceSizeKBytes(sourceMimetype, targetMimetype, options);
boolean sizeOkay = maxSourceSizeKBytes < 0 || (maxSourceSizeKBytes > 0 && sourceSize <= maxSourceSizeKBytes*1024);
AlfrescoRuntimeException e = new UnsupportedTransformationException("Unsupported transformation: " +
getBeanName()+' '+sourceMimetype+" to "+targetMimetype+' '+
(sizeOkay
? ""
: transformerDebug.fileSize(sourceSize)+" > "+ transformerDebug.fileSize(maxSourceSizeKBytes*1024)));
throw transformerDebug.setCause(e);
}
// it all checks out OK
}
/**
* Method to be implemented by subclasses wishing to make use of the common infrastructural code
* provided by this class.
*
* @param reader the source of the content to transform
* @param writer the target to which to write the transformed content
* @param options a map of options to use when performing the transformation. The map
* will never be null.
* @throws Exception exceptions will be handled by this class - subclasses can throw anything
*/
protected abstract void transformInternal(
ContentReader reader,
ContentWriter writer,
TransformationOptions options) throws Exception;
/**
* @see #transform(ContentReader, ContentWriter, Map)
* @see #transformInternal(ContentReader, ContentWriter, TransformationOptions)
*/
public final void transform(ContentReader reader, ContentWriter writer) throws ContentIOException
{
transform(reader, writer, new TransformationOptions());
}
/**
* @see org.alfresco.repo.content.transform.ContentTransformer#transform(org.alfresco.service.cmr.repository.ContentReader, org.alfresco.service.cmr.repository.ContentWriter, org.alfresco.service.cmr.repository.TransformationOptions)
*/
public void transform(ContentReader reader, ContentWriter writer, TransformationOptions options)
throws ContentIOException
{
try
{
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)
{
options = new TransformationOptions();
}
try
{
if (transformerDebug.isEnabled())
{
((LegacyTransformerDebug)transformerDebug).pushTransform(this, reader.getContentUrl(), sourceMimetype,
targetMimetype, reader.getSize(), options);
}
// MNT-16381: check the mimetype of the file supplied by the user
// matches the sourceMimetype of the reader. Intermediate files are
// not checked.
strictMimetypeCheck(reader, options, sourceMimetype);
// Check the transformability
checkTransformable(reader, writer, options);
// Pass on any limits to the reader
setReaderLimits(reader, writer, options);
// Transform
// MNT-12238: CLONE - CLONE - Upload of PPTX causes very high memory usage leading to system instability
// Limiting transformation up to configured amount of milliseconds to avoid very high RAM consumption
// and OOM during transforming problematic documents
TransformationOptionLimits limits = getLimits(reader.getMimetype(), writer.getMimetype(), options);
long timeoutMs = limits.getTimeoutMs();
if (!useTimeoutThread || (null == limits) || (-1 == timeoutMs))
{
transformInternal(reader, writer, options);
}
else
{
Future<?> submittedTask = null;
StreamAwareContentReaderProxy proxiedReader = new StreamAwareContentReaderProxy(reader);
StreamAwareContentWriterProxy proxiedWriter = new StreamAwareContentWriterProxy(writer);
try
{
submittedTask = getExecutorService().submit(new TransformInternalCallable(proxiedReader, proxiedWriter, options));
submittedTask.get(timeoutMs + additionalThreadTimout, TimeUnit.MILLISECONDS);
}
catch (TimeoutException e)
{
releaseResources(submittedTask, proxiedReader, proxiedWriter);
throw new TimeoutException("Transformation failed due to timeout limit");
}
catch (InterruptedException e)
{
releaseResources(submittedTask, proxiedReader, proxiedWriter);
throw new InterruptedException("Transformation failed, because the thread of the transformation was interrupted");
}
catch (ExecutionException e)
{
Throwable cause = e.getCause();
if (cause instanceof TransformInternalCallableException)
{
cause = ((TransformInternalCallableException) cause).getCause();
}
throw cause;
}
}
// record time
long after = System.currentTimeMillis();
recordTime(sourceMimetype, targetMimetype, after - before);
}
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 (UnsupportedTransformationException e)
{
// Don't record an error or even the time, as this is normal in compound transformations.
transformerDebug.debug(" Failed", e);
throw e;
}
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
long after = System.currentTimeMillis();
recordError(sourceMimetype, targetMimetype, after - before);
// 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);
if (retryTransformOnDifferentMimeType)
{
// MNT-11015 fix.
// Set a new reader to refresh the input stream.
reader = reader.getReader();
// set the actual file MIME type detected by Tika for content reader
reader.setMimetype(differentType);
// Get correct transformer according actual file MIME type and try to transform file with
// actual transformer
ContentTransformer transformer = this.registry.getTransformer(differentType, reader.getSize(),
targetMimetype, options);
if (null != transformer)
{
transformer.transform(reader, writer, options);
}
else
{
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) + "\n" +
" claimed mime type: " + reader.getMimetype() + "\n" +
" detected mime type: " + differentType + "\n" +
" transformer not found" + "\n",
e
);
}
}
else
{
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);
}
}
// done
if (logger.isDebugEnabled())
{
logger.debug("Completed transformation: \n" +
" reader: " + reader + "\n" +
" writer: " + writer + "\n" +
" options: " + options + "\n" +
" transformer: " + this);
}
}
finally
{
depth.set(depth.get()-1);
}
}
private void strictMimetypeCheck(ContentReader reader, TransformationOptions options, String sourceMimetype)
throws UnsupportedTransformationException
{
if (strictMimeTypeCheck && depth.get() == 1)
{
String differentType = getMimetypeService().getMimetypeIfNotMatches(reader.getReader());
if (!transformerConfig.strictMimetypeCheck(sourceMimetype, differentType))
{
String fileName = ((LegacyTransformerDebug)transformerDebug).getFileName(options, true, 0);
String readerSourceMimetype = reader.getMimetype();
String message = "Transformation of ("+fileName+
") has not taken place because the declared mimetype ("+
readerSourceMimetype+") does not match the detected mimetype ("+
differentType+").";
logger.warn(message);
throw new UnsupportedTransformationException(message);
}
}
}
/**
* Cancels <code>task</code> and closes content accessors
*
* @param task - {@link Future} task instance which specifies a transformation action
* @param proxiedReader - {@link AbstractStreamAwareProxy} instance which represents channel closing mechanism for content reader
* @param proxiedWriter - {@link AbstractStreamAwareProxy} instance which represents channel closing mechanism for content writer
*/
private void releaseResources(Future<?> task, AbstractStreamAwareProxy proxiedReader, AbstractStreamAwareProxy proxiedWriter)
{
if (null != task)
{
task.cancel(true);
}
if (null != proxiedReader)
{
proxiedReader.release();
}
if (null != proxiedWriter)
{
proxiedWriter.release();
}
}
public final void transform(
ContentReader reader,
ContentWriter writer,
Map<String, Object> options) throws ContentIOException
{
this.transform(reader, writer, new TransformationOptions(options));
}
/**
* @return Returns the calculated running average of the current transformations
*/
public synchronized long getTransformationTime()
{
return transformerConfig.getStatistics(this, null, null, true).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, true).getAverageTime();
}
/**
* @deprecated use method with mimetypes.
*/
protected final synchronized void recordTime(long transformationTime)
{
recordTime(TransformerConfig.ANY, TransformerConfig.ANY, transformationTime);
}
/**
* Records and updates the average transformation time for this transformer.
* <p>
* Subclasses should call this after every transformation in order to keep
* the running average of the transformation times up to date.
* <p>
* This method is thread-safe. The time spent in this method is negligible
* so the impact will be minor.
*
* @param sourceMimetype String
* @param targetMimetype String
* @param transformationTime the time it took to perform the transformation.
*/
protected final synchronized void recordTime(String sourceMimetype, String targetMimetype,
long transformationTime)
{
transformerConfig.getStatistics(this, sourceMimetype, targetMimetype, true).recordTime(transformationTime);
if (depth.get() == 1)
{
transformerConfig.getStatistics(null, sourceMimetype, targetMimetype, true).recordTime(transformationTime);
}
}
/**
* Gets the <code>ExecutorService</code> to be used for timeout-aware extraction.
* <p>
* If no <code>ExecutorService</code> has been defined a default of <code>Executors.newCachedThreadPool()</code> is used during {@link AbstractMappingMetadataExtracter}.
*
* @return the defined or default <code>ExecutorService</code>
*/
protected ExecutorService getExecutorService()
{
if (null == executorService)
{
executorService = Executors.newCachedThreadPool();
}
return executorService;
}
/**
* Sets the <code>ExecutorService</code> to be used for timeout-aware transformation.
*
* @param executorService - {@link ExecutorService} instance for timeouts
*/
public void setExecutorService(ExecutorService executorService)
{
this.executorService = executorService;
}
/**
* {@link Callable} wrapper for the {@link AbstractContentTransformer2#transformInternal(ContentReader, ContentWriter, TransformationOptions)} method to handle timeouts.
*/
private class TransformInternalCallable implements Callable<Void>
{
private ContentReader reader;
private ContentWriter writer;
private TransformationOptions options;
public TransformInternalCallable(ContentReader reader, ContentWriter writer, TransformationOptions options)
{
this.reader = reader;
this.writer = writer;
this.options = options;
}
@Override
public Void call() throws Exception
{
try
{
transformInternal(reader, writer, options);
return null;
}
catch (Throwable e)
{
throw new TransformInternalCallableException(e);
}
}
}
/**
* Exception wrapper to handle any {@link Throwable} from {@link AbstractContentTransformer2#transformInternal(ContentReader, ContentWriter, TransformationOptions)}
*/
private class TransformInternalCallableException extends Exception
{
private static final long serialVersionUID = 7740560508772740658L;
public TransformInternalCallableException(Throwable cause)
{
super(cause);
}
}
/**
* @param useTimeoutThread - {@link Boolean} value which specifies timeout limiting mechanism for the current transformer
* @see AbstractContentTransformer2#useTimeoutThread
*/
public void setUseTimeoutThread(Boolean useTimeoutThread)
{
if (null == useTimeoutThread)
{
useTimeoutThread = true;
}
this.useTimeoutThread = useTimeoutThread;
}
public void setAdditionalThreadTimout(long additionalThreadTimout)
{
this.additionalThreadTimout = additionalThreadTimout;
}
public Boolean isTransformationLimitedInternally()
{
return useTimeoutThread;
}
/**
* 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 String
* @param targetMimetype String
* @param transformationTime the time it took to perform the transformation.
*/
protected final synchronized void recordError(String sourceMimetype, String targetMimetype,
long transformationTime)
{
transformerConfig.getStatistics(this, sourceMimetype, targetMimetype, true).recordError(transformationTime);
if (depth.get() == 1)
{
transformerConfig.getStatistics(null, sourceMimetype, targetMimetype, true).recordError(transformationTime);
}
}
public Object getRetryTransformOnDifferentMimeType()
{
return retryTransformOnDifferentMimeType;
}
public void setRetryTransformOnDifferentMimeType(boolean retryTransformOnDifferentMimeType)
{
this.retryTransformOnDifferentMimeType = retryTransformOnDifferentMimeType;
}
public boolean getStrictMimeTypeCheck()
{
return strictMimeTypeCheck;
}
public void setStrictMimeTypeCheck(boolean strictMimeTypeCheck)
{
this.strictMimeTypeCheck = strictMimeTypeCheck;
}
}

View File

@@ -1,377 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
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.api.AlfrescoPublicApi;
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.TransformationOptionLimits;
import org.alfresco.service.cmr.repository.TransformationOptions;
/**
* Provides transformation limits for {@link org.alfresco.repo.content.transform.ContentTransformer}
* implementations.
* <p>
* This class maintains the limits and provides methods that combine limits:
* a) for the transformer as a whole
* b) for specific combinations if source and target mimetypes
* c) for the {@link TransformationOptions} provided for a specific transform.
*
* @author Alan Davis
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
@AlfrescoPublicApi
public abstract class AbstractContentTransformerLimits extends ContentTransformerHelper implements ContentTransformer
{
/** Indicates if 'page' limits are supported. */
private boolean pageLimitsSupported;
/** For debug **/
protected TransformerDebug transformerDebug;
/**
* Indicates if 'page' limits are supported.
* @return false by default.
*/
protected boolean isPageLimitSupported(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
return pageLimitsSupported;
}
/**
* Indicates if 'page' limits are supported.
*/
public void setPageLimitsSupported(boolean pageLimitsSupported)
{
this.pageLimitsSupported = pageLimitsSupported;
}
/**
* Helper setter of the transformer debug.
* @param transformerDebug TransformerDebug
*/
public void setTransformerDebug(TransformerDebug transformerDebug)
{
this.transformerDebug = transformerDebug;
}
public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
throw new IllegalStateException("Method should no longer be called. Override isTransformableMimetype in subclass.");
}
/**
* {@inheritDoc}<p>
*
* Implementation calls the deprecated overloaded method without the sourceSize parameter
* and then {@link #isTransformableSize(String, long, String, TransformationOptions)}.
*/
@Override
public boolean isTransformable(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options)
{
// To make TransformerDebug output clearer, check the mimetypes and then the sizes.
// If not done, 'unavailable' transformers due to size might be reported even
// though they cannot transform the source to the target mimetype.
return
isSupportedTransformation(sourceMimetype, targetMimetype, options) &&
isTransformableMimetype(sourceMimetype, targetMimetype, options) &&
isTransformableSize(sourceMimetype, sourceSize, targetMimetype, options);
}
/**
* Indicates if this transformer is able to transform the given source mimetype
* to the target mimetype. If overridden, consider also overriding
* {@link ContentTransformerHelper#getComments(boolean)}.
*/
@Override
public boolean isTransformableMimetype(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
return isTransformable(sourceMimetype, targetMimetype, options);
}
/**
* Indicates if this transformer is able to transform the given {@code sourceSize}.
* The {@code maxSourceSizeKBytes} property may indicate that only small source files
* may be transformed.
* @param sourceSize size in bytes of the source. If negative, the source size is unknown.
* @return {@code true} if the source is transformable.
*/
@Override
public boolean isTransformableSize(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options)
{
boolean sizeOkay = true;
if (sourceSize >= 0)
{
// if maxSourceSizeKBytes == 0 this implies the transformation is disabled
long maxSourceSizeKBytes = getMaxSourceSizeKBytes(sourceMimetype, targetMimetype, options);
sizeOkay = maxSourceSizeKBytes < 0 || (maxSourceSizeKBytes > 0 && sourceSize <= maxSourceSizeKBytes*1024);
if (!sizeOkay && transformerDebug.isEnabled())
{
((LegacyTransformerDebug)transformerDebug).unavailableTransformer(this, sourceMimetype, targetMimetype, maxSourceSizeKBytes);
}
}
return sizeOkay;
}
/**
* Returns the maximum source size (in KBytes) allowed given the supplied values.
* @return 0 if the the transformation is disabled, -1 if there is no limit, otherwise the size in KBytes.
*/
@Override
public long getMaxSourceSizeKBytes(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
long maxSourceSizeKBytes = -1;
// The maxSourceSizeKbytes value is ignored if this transformer is able to use
// page limits and the limits include a pageLimit. Normally used in the creation
// of icons. Note the readLimitKBytes value is not checked as the combined limits
// only have the max or limit KBytes value set (the smaller value is returned).
TransformationOptionLimits limits = getLimits(sourceMimetype, targetMimetype, options);
if (!isPageLimitSupported(sourceMimetype, targetMimetype, options) || limits.getPageLimit() <= 0)
{
maxSourceSizeKBytes = limits.getMaxSourceSizeKBytes();
}
return maxSourceSizeKBytes;
}
/**
* @deprecated use {@link #getLimits(String, String, TransformationOptions) getTimeoutMs()}
* which allows the limits to be selected based on mimetype and use.
*/
protected long getTimeoutMs()
{
return getLimits().getTimeoutMs();
}
/**
* @deprecated transformation limits are now set with global properties rather than spring configuration.
*/
public void setTimeoutMs(long timeoutMs)
{
deprecatedSetter(null, null, OPT_TIMEOUT_MS+'='+timeoutMs);
}
/**
* @deprecated use {@link #getLimits(String, String, TransformationOptions) getReadLimitTimeMs()}
* which allows the limits to be selected based on mimetype and use.
*/
protected long getReadLimitTimeMs()
{
return getLimits().getReadLimitTimeMs();
}
/**
* @deprecated transformation limits are now set with global properties rather than spring configuration.
*/
public void setReadLimitTimeMs(long readLimitTimeMs)
{
deprecatedSetter(null, null, OPT_READ_LIMIT_TIME_MS+'='+readLimitTimeMs);
}
/**
* @deprecated use {@link #getLimits(String, String, TransformationOptions) getMaxSourceSizeKBytes()}
* which allows the limits to be selected based on mimetype and use.
*/
protected long getMaxSourceSizeKBytes()
{
return getLimits().getMaxSourceSizeKBytes();
}
/**
* @deprecated transformation limits are now set with global properties rather than spring configuration.
*/
public void setMaxSourceSizeKBytes(long maxSourceSizeKBytes)
{
deprecatedSetter(null, null, OPT_MAX_SOURCE_SIZE_K_BYTES+'='+maxSourceSizeKBytes);
}
/**
* @deprecated use {@link #getLimits(String, String, TransformationOptions) getReadLimitKBytes()}
* which allows the limits to be selected based on mimetype and use.
*/
protected long getReadLimitKBytes()
{
return getLimits().getReadLimitKBytes();
}
/**
* @deprecated transformation limits are now set with global properties rather than spring configuration.
*/
public void setReadLimitKBytes(long readLimitKBytes)
{
deprecatedSetter(null, null, OPT_READ_LIMIT_K_BYTES+'='+readLimitKBytes);
}
/**
* @deprecated use {@link #getLimits(String, String, TransformationOptions) getMaxPages()}
* which allows the limits to be selected based on mimetype and use.
*/
protected int getMaxPages()
{
return getLimits().getMaxPages();
}
/**
* @deprecated transformation limits are now set with global properties rather than spring configuration.
*/
public void setMaxPages(int maxPages)
{
deprecatedSetter(null, null, OPT_MAX_PAGES+'='+maxPages);
}
/**
* @deprecated use {@link #getLimits(String, String, TransformationOptions) getPageLimit()}
* which allows the limits to be selected based on mimetype and use.
*/
protected int getPageLimit()
{
return getLimits().getPageLimit();
}
/**
* @deprecated transformation limits are now set with global properties rather than spring configuration.
*/
public void setPageLimit(int pageLimit)
{
deprecatedSetter(null, null, OPT_PAGE_LIMIT+'='+pageLimit);
}
/**
* @deprecated use {@link #getLimits(String, String, TransformationOptions)} which allows the
* limits to be selected based on mimetype and use.
*/
protected TransformationOptionLimits getLimits()
{
return transformerConfig.getLimits(this, null, null, null);
}
/**
* @deprecated transformation limits are now set with global properties rather than spring configuration.
*/
public void setLimits(TransformationOptionLimits limits)
{
deprecatedLimitsSetter(null, null, limits);
}
/**
* @deprecated transformation limits are now set with global properties rather than spring configuration.
*/
public void setMimetypeLimits(Map<String, Map<String, TransformationOptionLimits>> mimetypeLimits)
{
for (Entry<String, Map<String, TransformationOptionLimits>> source: mimetypeLimits.entrySet())
{
String sourceMimetype = source.getKey();
for (Entry<String, TransformationOptionLimits> target: source.getValue().entrySet())
{
String targetMimetype = target.getKey();
TransformationOptionLimits limits = target.getValue();
deprecatedLimitsSetter(sourceMimetype, targetMimetype, limits);
}
}
}
private void deprecatedLimitsSetter(String sourceMimetype, String targetMimetype, 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(sourceMimetype, targetMimetype, '.'+limit);
}
}
}
else
{
deprecatedSetter(sourceMimetype, targetMimetype, TransformerConfig.SUPPORTED+"=false");
}
}
/**
* Returns max and limit values for time, size and pages for a specified source and
* target mimetypes, combined with this Transformer's general limits and optionally
* the supplied transformation option's limits.
*/
protected TransformationOptionLimits getLimits(ContentReader reader, ContentWriter writer,
TransformationOptions options)
{
return (reader == null || writer == null)
? transformerConfig.getLimits(this, null, null, options.getUse()).combine(options.getLimits())
: getLimits(reader.getMimetype(), writer.getMimetype(), options);
}
/**
* Returns max and limit values for time, size and pages for a specified source and
* target mimetypes, combined with this Transformer's general limits and optionally
* the supplied transformation option's limits.
*/
protected TransformationOptionLimits getLimits(String sourceMimetype, String targetMimetype,
TransformationOptions options)
{
TransformationOptionLimits limits = transformerConfig.getLimits(this, sourceMimetype, targetMimetype, (options == null ? null : options.getUse()));
return (options == null) ? limits : limits.combine(options.getLimits());
}
/**
* Pass on any limits to the reader. Will only do so if the reader is an
* {@link AbstractContentReader}.
* @param reader passed to {@link #transform(ContentReader, ContentWriter, TransformationOptions)}.
* @param writer passed to {@link #transform(ContentReader, ContentWriter, TransformationOptions)}.
* @param options passed to {@link #transform(ContentReader, ContentWriter, TransformationOptions)}.
*/
protected void setReaderLimits(ContentReader reader, ContentWriter writer,
TransformationOptions options)
{
if (reader instanceof AbstractContentReader)
{
AbstractContentReader abstractContentReader = (AbstractContentReader)reader;
TransformationOptionLimits limits = getLimits(reader, writer, options);
abstractContentReader.setLimits(limits);
abstractContentReader.setTransformerDebug(transformerDebug);
}
}
}

View File

@@ -1,205 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import org.alfresco.error.AlfrescoRuntimeException;
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.alfresco.util.Pair;
import org.apache.commons.logging.Log;
/**
* Optionally sends transformations to a remote transformer if a {@link RemoteTransformerClient} is set and
* the ".url" Alfresco global property is set.
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public abstract class AbstractRemoteContentTransformer extends AbstractContentTransformer2
{
private boolean enabled = true;
private RemoteTransformerClient remoteTransformerClient;
private boolean available = false;
public void setEnabled(boolean enabled)
{
this.enabled = enabled;
}
/**
* Sets the optional remote transformer client which will be used in preference to a local command if available.
*
* @param remoteTransformerClient may be null;
*/
public void setRemoteTransformerClient(RemoteTransformerClient remoteTransformerClient)
{
this.remoteTransformerClient = remoteTransformerClient;
}
boolean remoteTransformerClientConfigured()
{
return remoteTransformerClient != null && remoteTransformerClient.getBaseUrl() != null;
}
protected abstract Log getLogger();
/**
* THIS IS A CUSTOM SPRING INIT METHOD
*/
@Override
public void register()
{
super.register();
afterPropertiesSet();
}
public void afterPropertiesSet()
{
if (enabled)
{
// check availability
if (remoteTransformerClientConfigured())
{
Log logger = getLogger();
try
{
Pair<Boolean, String> result = remoteTransformerClient.check(logger);
Boolean isAvailable = result.getFirst();
String msg = result.getSecond() == null ? "" : result.getSecond();
if (isAvailable != null && isAvailable)
{
String versionString = msg;
setAvailable(true);
logger.debug("Using legacy " + getName() + ": " + versionString);
}
else
{
setAvailable(false);
String message = "Legacy " + getName() + " is not available for transformations. " + msg;
if (isAvailable == null)
{
logger.debug(message);
}
else
{
logger.error(message);
}
}
}
catch (Throwable e)
{
setAvailable(false);
logger.error("Remote " + getName() + " is not available: " + (e.getMessage() != null ? e.getMessage() : ""));
// debug so that we can trace the issue if required
logger.debug(e);
}
}
else
{
available = true;
}
}
}
public boolean isAvailable()
{
if (remoteTransformerClientConfigured() && !remoteTransformerClient.isAvailable())
{
afterPropertiesSet();
}
return available;
}
protected void setAvailable(boolean available)
{
this.available = available;
}
@Override
public boolean isTransformable(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options)
{
if (!isAvailable())
{
return false;
}
return super.isTransformable(sourceMimetype, sourceSize, targetMimetype, options);
}
public void transformInternal(ContentReader reader, ContentWriter writer, TransformationOptions options)
throws Exception
{
if (remoteTransformerClientConfigured())
{
String sourceMimetype = getMimetype(reader);
String targetMimetype = writer.getMimetype();
String targetEncoding = writer.getEncoding();
MimetypeService mimetypeService = getMimetypeService();
String sourceExtension = mimetypeService.getExtension(sourceMimetype);
String targetExtension = mimetypeService.getExtension(targetMimetype);
if (sourceExtension == null || targetExtension == null)
{
throw new AlfrescoRuntimeException("Unknown extensions for mimetypes: \n" +
" source mimetype: " + sourceMimetype + "\n" +
" source extension: " + sourceExtension + "\n" +
" target mimetype: " + targetMimetype + "\n" +
" target extension: " + targetExtension + "\n" +
" target encoding: " + targetEncoding);
}
transformRemote(remoteTransformerClient, reader, writer, options, sourceMimetype, targetMimetype,
sourceExtension, targetExtension, targetEncoding);
}
else
{
transformLocal(reader, writer, options);
}
Log logger = getLogger();
if (logger.isDebugEnabled())
{
logger.debug("Transformation completed: \n" +
" source: " + reader + "\n" +
" target: " + writer + "\n" +
" options: " + options);
}
}
protected abstract void transformLocal(ContentReader reader, ContentWriter writer, TransformationOptions options)
throws Exception;
protected abstract void transformRemote(RemoteTransformerClient remoteTransformerClient, ContentReader reader,
ContentWriter writer, TransformationOptions options,
String sourceMimetype, String targetMimetype,
String sourceExtension, String targetExtension,
String targetEncoding) throws Exception;
}

View File

@@ -67,16 +67,16 @@ import java.util.regex.Pattern;
public class AdminUiTransformerDebug extends TransformerDebug implements ApplicationContextAware
{
protected TransformServiceRegistry remoteTransformServiceRegistry;
protected LocalTransformServiceRegistry localTransformServiceRegistryImpl;
protected LocalTransformServiceRegistry localTransformServiceRegistry;
private ApplicationContext applicationContext;
private ContentService contentService;
private SynchronousTransformClient synchronousTransformClient;
private Repository repositoryHelper;
private TransactionService transactionService;
public void setLocalTransformServiceRegistryImpl(LocalTransformServiceRegistry localTransformServiceRegistryImpl)
public void setLocalTransformServiceRegistry(LocalTransformServiceRegistry localTransformServiceRegistry)
{
this.localTransformServiceRegistryImpl = localTransformServiceRegistryImpl;
this.localTransformServiceRegistry = localTransformServiceRegistry;
}
public void setRemoteTransformServiceRegistry(TransformServiceRegistry remoteTransformServiceRegistry)
@@ -108,7 +108,7 @@ public class AdminUiTransformerDebug extends TransformerDebug implements Applica
{
if (synchronousTransformClient == null)
{
synchronousTransformClient = (SynchronousTransformClient) applicationContext.getBean("legacySynchronousTransformClient");
synchronousTransformClient = (SynchronousTransformClient) applicationContext.getBean("synchronousTransformClient");
}
return synchronousTransformClient;
}
@@ -150,7 +150,7 @@ public class AdminUiTransformerDebug extends TransformerDebug implements Applica
public void afterPropertiesSet() throws Exception
{
super.afterPropertiesSet();
PropertyCheck.mandatory(this, "localTransformServiceRegistryImpl", localTransformServiceRegistryImpl);
PropertyCheck.mandatory(this, "localTransformServiceRegistry", localTransformServiceRegistry);
PropertyCheck.mandatory(this, "remoteTransformServiceRegistry", remoteTransformServiceRegistry);
}
@@ -160,12 +160,8 @@ public class AdminUiTransformerDebug extends TransformerDebug implements Applica
* @param sourceExtension restricts the list to one source extension. Unrestricted if null.
* @param targetExtension restricts the list to one target extension. Unrestricted if null.
* @param toString indicates that a String value should be returned in addition to any debug.
* @param format42 ignored
* @param onlyNonDeterministic ignored
* @param renditionName ignored
*/
public String transformationsByExtension(String sourceExtension, String targetExtension, boolean toString,
boolean format42, boolean onlyNonDeterministic, String renditionName)
public String transformationsByExtension(String sourceExtension, String targetExtension, boolean toString)
{
// Do not generate this type of debug if already generating other debug to a StringBuilder
// (for example a test transform).
@@ -174,10 +170,10 @@ public class AdminUiTransformerDebug extends TransformerDebug implements Applica
return null;
}
Collection<String> sourceMimetypes = format42 || sourceExtension != null
Collection<String> sourceMimetypes = sourceExtension != null
? getSourceMimetypes(sourceExtension)
: mimetypeService.getMimetypes();
Collection<String> targetMimetypes = format42 || targetExtension != null
Collection<String> targetMimetypes = targetExtension != null
? getTargetMimetypes(sourceExtension, targetExtension, sourceMimetypes)
: mimetypeService.getMimetypes();
@@ -200,9 +196,9 @@ public class AdminUiTransformerDebug extends TransformerDebug implements Applica
? false
: remoteTransformServiceRegistry.isSupported(sourceMimetype,
-1, targetMimetype, Collections.emptyMap(), null);
List<SupportedTransform> localTransformers = localTransformServiceRegistryImpl == null
List<SupportedTransform> localTransformers = localTransformServiceRegistry == null
? Collections.emptyList()
: localTransformServiceRegistryImpl.findTransformers(sourceMimetype,
: localTransformServiceRegistry.findTransformers(sourceMimetype,
targetMimetype, Collections.emptyMap(), null);
if (!localTransformers.isEmpty() || supportedByTransformService)
{
@@ -327,9 +323,9 @@ public class AdminUiTransformerDebug extends TransformerDebug implements Applica
}
public String testTransform(String sourceExtension, String targetExtension, String renditionName)
public String testTransform(String sourceExtension, String targetExtension)
{
return new TestTransform().run(sourceExtension, targetExtension, renditionName);
return new TestTransform().run(sourceExtension, targetExtension);
}
public String[] getTestFileExtensionsAndMimetypes()
@@ -369,7 +365,7 @@ public class AdminUiTransformerDebug extends TransformerDebug implements Applica
{
protected LinkedList<NodeRef> nodesToDeleteAfterTest = new LinkedList<NodeRef>();
String run(String sourceExtension, String targetExtension, String renditionName)
String run(String sourceExtension, String targetExtension)
{
RetryingTransactionHelper.RetryingTransactionCallback<String> makeNodeCallback = new RetryingTransactionHelper.RetryingTransactionCallback<String>()
{
@@ -403,7 +399,7 @@ public class AdminUiTransformerDebug extends TransformerDebug implements Applica
}
catch (Exception e)
{
logger.debug("Unexpected test transform error", e);
sb.append(e.getMessage());
}
finally
{

View File

@@ -1,169 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2017 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
/**
* Converts Apple iWorks files to JPEGs for thumbnailing & previewing.
* The transformer will only work for iWorks 2013/14 files. Support for iWorks 2008/9 has been dropped as we cannot
* support both, because the newer format does not contain a PDF. If we say this transformer supports PDF, Share will
* assume incorrectly that we can convert to PDF and we would only get a preview for the older format and never the
* newer one. Both formats have the same mimetype.
*
* @author Neil Mc Erlean
* @since 4.0
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public class AppleIWorksContentTransformer extends AbstractRemoteContentTransformer
{
private static final Log logger = LogFactory.getLog(AppleIWorksContentTransformer.class);
// Apple's zip entry names for previews in iWorks have changed over time.
private static final List<String> PDF_PATHS = Arrays.asList(
"QuickLook/Preview.pdf"); // iWorks 2008/9
private static final List<String> JPG_PATHS = Arrays.asList(
"QuickLook/Thumbnail.jpg", // iWorks 2008/9
"preview.jpg"); // iWorks 2013/14 (720 x 552) We use the best quality image. Others are:
// (225 x 173) preview-web.jpg
// (53 x 41) preview-micro.jpg
private static final List<String> IWORKS_MIMETYPES = Arrays.asList(MimetypeMap.MIMETYPE_IWORK_KEYNOTE,
MimetypeMap.MIMETYPE_IWORK_NUMBERS,
MimetypeMap.MIMETYPE_IWORK_PAGES);
private static final List<String> TARGET_MIMETYPES = Arrays.asList(MimetypeMap.MIMETYPE_IMAGE_JPEG
// Commented out rather than removed, in case we can get SHARE to fall back to using JPEG when a PDF is not available
// ,MimetypeMap.MIMETYPE_PDF
);
@Override
public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
// only support [iWorks] -> JPEG but only if these are embedded in the file.
// This is because iWorks 13+ files are zip files containing embedded jpeg previews.
return TARGET_MIMETYPES.contains(targetMimetype) && IWORKS_MIMETYPES.contains(sourceMimetype);
}
@Override
public String getComments(boolean available)
{
return getCommentsOnlySupports(IWORKS_MIMETYPES, TARGET_MIMETYPES, available);
}
@Override
protected Log getLogger()
{
return logger;
}
@Override
protected void transformLocal(ContentReader reader,
ContentWriter writer,
TransformationOptions options) throws Exception
{
final String sourceMimetype = reader.getMimetype();
final String sourceExtension = getMimetypeService().getExtension(sourceMimetype);
final String targetMimetype = writer.getMimetype();
final String targetExtension = getMimetypeService().getExtension(targetMimetype);
if (logger.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Transforming from ").append(sourceMimetype)
.append(" to ").append(targetMimetype);
logger.debug(msg.toString());
}
ZipArchiveInputStream iWorksZip = null;
try
{
// iWorks files are zip (or package) files.
// If it's not a zip file, the resultant ZipException will be caught as an IOException below.
iWorksZip = new ZipArchiveInputStream(reader.getContentInputStream());
// Look through the zip file entries for the preview/thumbnail.
List<String> paths = MimetypeMap.MIMETYPE_IMAGE_JPEG.equals(targetMimetype) ? JPG_PATHS : PDF_PATHS;
ZipArchiveEntry entry;
boolean found = false;
while ((entry=iWorksZip.getNextZipEntry()) != null)
{
String name = entry.getName();
if (paths.contains(name))
{
writer.putContent( iWorksZip );
found = true;
break;
}
}
if (! found)
{
throw new AlfrescoRuntimeException("The source " + sourceExtension + " file did not contain a " + targetExtension + " preview");
}
}
catch (IOException e)
{
throw new AlfrescoRuntimeException("Unable to transform " + sourceExtension + " file. It should have been a zip format file.", e);
}
finally
{
if (iWorksZip != null)
{
iWorksZip.close();
}
}
}
@Override
protected void transformRemote(RemoteTransformerClient remoteTransformerClient, ContentReader reader,
ContentWriter writer, TransformationOptions options, String sourceMimetype,
String targetMimetype, String sourceExtension, String targetExtension,
String targetEncoding) throws Exception
{
long timeoutMs = options.getTimeoutMs();
remoteTransformerClient.request(reader, writer, sourceMimetype, sourceExtension, targetExtension,
timeoutMs, logger,
"transformName", "appleIWorks",
"sourceMimetype", sourceMimetype,
"sourceExtension", sourceExtension,
"targetMimetype", targetMimetype);
}
}

View File

@@ -1,168 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import java.util.ArrayList;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tika.config.TikaConfig;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MediaType;
import org.apache.tika.parser.AutoDetectParser;
import org.apache.tika.parser.EmptyParser;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.Parser;
import org.apache.tika.parser.pkg.PackageParser;
import static org.alfresco.repo.rendition2.RenditionDefinition2.TARGET_ENCODING;
/**
* This class transforms archive files (zip, tar etc) to text, which enables indexing
* and searching of archives as well as webpreviewing.
* The transformation can simply list the names of the entries within the archive, or
* it can also include the textual content of the entries themselves.
* The former is suggested for web preview, the latter for indexing.
* This behaviour is controlled by the recurse flag.
*
* @author Neil McErlean
* @author Nick Burch
* @since 3.4
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public class ArchiveContentTransformer extends TikaPoweredContentTransformer
{
/**
* The logger
*/
private static Log logger = LogFactory.getLog(ArchiveContentTransformer.class);
private boolean includeContents = false;
private TikaConfig tikaConfig;
/**
* We support all the archive mimetypes that the Tika
* package parser can handle
*/
public static ArrayList<String> SUPPORTED_MIMETYPES;
static {
SUPPORTED_MIMETYPES = new ArrayList<String>();
Parser p = new PackageParser();
for(MediaType mt : p.getSupportedTypes(null)) {
// Tika can probably do some useful text
SUPPORTED_MIMETYPES.add( mt.toString() );
}
}
public ArchiveContentTransformer() {
super(SUPPORTED_MIMETYPES);
}
/**
* Injects the TikaConfig to use
*
* @param tikaConfig The Tika Config to use
*/
public void setTikaConfig(TikaConfig tikaConfig)
{
this.tikaConfig = tikaConfig;
}
public void setIncludeContents(String includeContents)
{
// Spring really ought to be able to handle
// setting a boolean that might still be
// ${foo} (i.e. not overridden in a property).
// As we can't do that with spring, we do it...
this.includeContents = false;
if(includeContents != null && includeContents.length() > 0)
{
this.includeContents = TransformationOptions.relaxedBooleanTypeConverter.convert(includeContents).booleanValue();
}
}
@Override
protected Parser getParser() {
return new PackageParser();
}
@Override
protected ParseContext buildParseContext(Metadata metadata,
String targetMimeType, TransformationOptions options) {
ParseContext context = super.buildParseContext(metadata, targetMimeType, options);
boolean recurse = includeContents;
if(options.getIncludeEmbedded() != null)
{
recurse = options.getIncludeEmbedded();
}
if(recurse)
{
// Use an auto detect parser to handle the contents
if(tikaConfig == null)
{
tikaConfig = TikaConfig.getDefaultConfig();
}
context.set(Parser.class, new AutoDetectParser(tikaConfig));
}
else
{
// REPO-1066: an AutoDetectParser is the default in Tika after: https://issues.apache.org/jira/browse/TIKA-2096
// so we need to specify an empty one if we don't want the recurse parsing to happen
context.set(Parser.class, new EmptyParser());
}
return context;
}
@Override
protected void transformRemote(RemoteTransformerClient remoteTransformerClient, ContentReader reader,
ContentWriter writer, TransformationOptions options,
String sourceMimetype, String targetMimetype,
String sourceExtension, String targetExtension,
String targetEncoding) throws Exception
{
long timeoutMs = options.getTimeoutMs();
boolean recurse = includeContents;
if(options.getIncludeEmbedded() != null)
{
recurse = options.getIncludeEmbedded();
}
remoteTransformerClient.request(reader, writer, sourceMimetype, sourceExtension, targetExtension,
timeoutMs, logger,
"transformName", "Archive",
"includeContents", Boolean.toString(recurse),
"sourceMimetype", sourceMimetype,
"sourceExtension", sourceExtension,
"targetMimetype", targetMimetype,
TARGET_ENCODING, targetEncoding);
}
}

View File

@@ -1,101 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Allows direct streaming from source to target when the respective mimetypes
* are identical, except where the mimetype is text.
* <p>
* Text has to be transformed based on the encoding even if the mimetypes don't
* reflect it.
*
* @see org.alfresco.repo.content.transform.StringExtractingContentTransformer
*
* @author Derek Hulley
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public class BinaryPassThroughContentTransformer extends AbstractContentTransformer2
{
@SuppressWarnings("unused")
private static final Log logger = LogFactory.getLog(BinaryPassThroughContentTransformer.class);
@Override
protected void transformInternal(ContentReader reader,
ContentWriter writer, TransformationOptions options)
throws Exception
{
// just stream it
writer.putContent(reader.getContentInputStream());
}
@Override
public boolean isTransformableMimetype(String sourceMimetype,
String targetMimetype, TransformationOptions options)
{
if (sourceMimetype.startsWith(StringExtractingContentTransformer.PREFIX_TEXT))
{
// we can only stream binary content through
return false;
}
else if (!sourceMimetype.equals(targetMimetype))
{
// no transformation is possible so formats must be exact
return false;
}
else
{
if (options == null || TransformationOptions.class.equals(options.getClass()) == true)
{
// formats are the same and are not text
return true;
}
else
{
// If it has meaningful options then we assume there is another transformer better equiped
// to deal with it
return false;
}
}
}
@Override
public String getComments(boolean available)
{
StringBuilder sb = new StringBuilder();
sb.append(super.getComments(available));
sb.append("# Only supports streaming to the same type but excludes txt\n");
return sb.toString();
}
}

View File

@@ -1,549 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import java.beans.PropertyDescriptor;
import java.io.File;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayDeque;
import java.util.Collections;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.alfresco.api.AlfrescoPublicApi;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.content.filestore.FileContentWriter;
import org.alfresco.repo.rendition2.LegacySynchronousTransformClient;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.TransformationOptionLimits;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.util.TempFileProvider;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
/**
* Transformer that passes a document through several nested transformations
* in order to accomplish its goal.
*
* @author Derek Hulley
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
@AlfrescoPublicApi
public class ComplexContentTransformer extends AbstractContentTransformer2 implements InitializingBean
{
/**
* The logger
*/
private static Log logger = LogFactory.getLog(ComplexContentTransformer.class);
/**
* Complex transformers contain lower level transformers. In order to find dynamic
* (defined as null) child transformers to use, they recursively check available
* transformers. It makes no sense to have a transformer that is its own child.
*/
static final ThreadLocal<Deque<ContentTransformer>> parentTransformers = new ThreadLocal<Deque<ContentTransformer>>() {
@Override
protected Deque<ContentTransformer> initialValue() {
return new ArrayDeque<ContentTransformer>();
}
};
private List<ContentTransformer> transformers;
private List<String> intermediateMimetypes;
private Map<String,Serializable> transformationOptionOverrides;
private LegacySynchronousTransformClient legacySynchronousTransformClient;
public ComplexContentTransformer()
{
}
/**
* The list of transformers to use. If any element is null
* all possible transformers will be considered. If any element
* is null, the legacySynchronousTransformClient property must be set.
* <p>
* If a single transformer is supplied, then it will still be used.
*
* @param transformers list of <b>at least one</b> transformer
*/
public void setTransformers(List<ContentTransformer> transformers)
{
this.transformers = transformers;
}
/**
* Set the intermediate mimetypes that the transformer must take the content
* through. If the transformation <b>A..B..C</b> is performed in order to
* simulate <b>A..C</b>, then <b>B</b> is the intermediate mimetype. There
* must always be <b>n-1</b> intermediate mimetypes, where <b>n</b> is the
* number of {@link #setTransformers(List) transformers} taking part in the
* transformation.
*
* @param intermediateMimetypes intermediate mimetypes to transition the content
* through.
*/
public void setIntermediateMimetypes(List<String> intermediateMimetypes)
{
this.intermediateMimetypes = intermediateMimetypes;
}
/**
* Sets any properties to be set on the TransformationOption as passed in.
* This allows you to force certain properties to always be set on it,
* to control the transformers in a different way to their default.
* Note that only properties that are supported by the passed-in
* {@link TransformationOptions} are changed, others are ignored.
*/
public void setTransformationOptionOverrides(
Map<String, Serializable> transformationOptionOverrides)
{
this.transformationOptionOverrides = transformationOptionOverrides;
}
public void setLegacySynchronousTransformClient(LegacySynchronousTransformClient legacySynchronousTransformClient)
{
this.legacySynchronousTransformClient = legacySynchronousTransformClient;
}
/**
* Ensures that required properties have been set
*/
public void afterPropertiesSet() throws Exception
{
if (transformers == null || transformers.size() == 0)
{
throw new AlfrescoRuntimeException("At least one inner transformer must be supplied: " + this);
}
if (intermediateMimetypes == null || intermediateMimetypes.size() != transformers.size() - 1)
{
throw new AlfrescoRuntimeException(
"There must be n-1 intermediate mimetypes, where n is the number of transformers");
}
if (getMimetypeService() == null)
{
throw new AlfrescoRuntimeException("'mimetypeService' is a required property");
}
for (ContentTransformer transformer: transformers)
{
if (transformer == null)
{
if (legacySynchronousTransformClient == null)
{
throw new AlfrescoRuntimeException("'legacySynchronousTransformClient' is a required property if " +
"there are any null (dynamic) transformers");
}
break;
}
}
}
@Override
public boolean isTransformable(String sourceMimetype, long sourceSize, String targetMimetype,
TransformationOptions options)
{
if (!isSupportedTransformation(sourceMimetype, targetMimetype, options))
{
return false;
}
// Don't allow transformer to be its own child.
if (parentTransformers.get().contains(this))
{
return false;
}
overrideTransformationOptions(options);
// Can use super isTransformableSize as it indirectly calls getLimits in this class
// which combines the limits from the first transformer. Other transformer in the chain
// are no checked as sizes are unknown.
return
isTransformableMimetype(sourceMimetype, targetMimetype, options) &&
isTransformableSize(sourceMimetype, sourceSize, targetMimetype, options);
}
/**
* Sets any transformation option overrides it can.
*/
private void overrideTransformationOptions(TransformationOptions options)
{
// Set any transformation options overrides if we can
if(options != null && transformationOptionOverrides != null)
{
for(String key : transformationOptionOverrides.keySet())
{
if(PropertyUtils.isWriteable(options, key))
{
try
{
PropertyDescriptor pd = PropertyUtils.getPropertyDescriptor(options, key);
Class<?> propertyClass = pd.getPropertyType();
Object value = transformationOptionOverrides.get(key);
if(value != null)
{
if(propertyClass.isInstance(value))
{
// Nothing to do
}
else if(value instanceof String && propertyClass.isInstance(Boolean.TRUE))
{
// Use relaxed converter
value = TransformationOptions.relaxedBooleanTypeConverter.convert((String)value);
}
else
{
value = DefaultTypeConverter.INSTANCE.convert(propertyClass, value);
}
}
PropertyUtils.setProperty(options, key, value);
}
catch(NoSuchMethodException nsme) {}
catch(InvocationTargetException ite) {}
catch(IllegalAccessException iae) {}
}
else
{
logger.warn("Unable to set override Transformation Option " + key + " on " + options);
}
}
}
}
@Override
public boolean isTransformableMimetype(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
boolean result = true;
String currentSourceMimetype = sourceMimetype;
Iterator<ContentTransformer> transformerIterator = transformers.iterator();
// When using a wild card (null) intermediate transformer, don't
// say we support a transformation that one of the none null intermediate
// transformers can do on its own, to avoid double transformations.
// Not done when there are no wild card transformers, as there are cases
// where it makes sense to go via an intermediate format (quality/speed).
while (transformerIterator.hasNext())
{
ContentTransformer transformer = transformerIterator.next();
if (transformer == null)
{
transformerIterator = transformers.iterator();
while (transformerIterator.hasNext())
{
transformer = transformerIterator.next();
if (transformer != null)
{
if (transformer.isTransformable(sourceMimetype, -1, targetMimetype, options))
{
return false;
}
}
}
break;
}
}
transformerIterator = transformers.iterator();
Iterator<String> intermediateMimetypeIterator = intermediateMimetypes.iterator();
while (transformerIterator.hasNext())
{
ContentTransformer transformer = transformerIterator.next();
// determine the target mimetype. This is the final target if we are on the last transformation
String currentTargetMimetype = transformerIterator.hasNext() ? intermediateMimetypeIterator.next() : targetMimetype;
if (transformer == null)
{
try
{
parentTransformers.get().push(this);
@SuppressWarnings("deprecation")
List<ContentTransformer> firstTansformers = legacySynchronousTransformClient.getActiveTransformers(
currentSourceMimetype, -1, currentTargetMimetype, options);
if (firstTansformers.isEmpty())
{
result = false;
break;
}
}
finally
{
parentTransformers.get().pop();
}
}
else
{
if (transformer.isTransformable(currentSourceMimetype, -1, currentTargetMimetype, options) == false)
{
result = false;
break;
}
}
// move on
currentSourceMimetype = currentTargetMimetype;
}
return result;
}
/**
* Indicates if 'page' limits are supported by the first transformer in the chain.
* If the first transformer is dynamic, all possible first transformers must support it.
* @return true if the first transformer supports them.
*/
@Override
protected boolean isPageLimitSupported(String sourceMimetype, String targetMimetype,
TransformationOptions options)
{
boolean pageLimitSupported;
ContentTransformer firstTransformer = transformers.get(0);
String firstTargetMimetype = intermediateMimetypes.get(0);
if (firstTransformer == null)
{
try
{
parentTransformers.get().push(this);
@SuppressWarnings("deprecation")
List<ContentTransformer> firstTansformers = legacySynchronousTransformClient.getActiveTransformers(
sourceMimetype, -1, firstTargetMimetype, options);
pageLimitSupported = !firstTansformers.isEmpty();
if (pageLimitSupported)
{
for (ContentTransformer transformer: firstTansformers)
{
if (!isPageLimitSupported(transformer, sourceMimetype, targetMimetype, options))
{
pageLimitSupported = false;
break;
}
}
}
}
finally
{
parentTransformers.get().pop();
}
}
else
{
pageLimitSupported = isPageLimitSupported(firstTransformer, sourceMimetype, targetMimetype, options);
}
return pageLimitSupported;
}
private boolean isPageLimitSupported(ContentTransformer transformer, String sourceMimetype,
String targetMimetype, TransformationOptions options)
{
return (transformer instanceof AbstractContentTransformerLimits)
? ((AbstractContentTransformerLimits)transformer).isPageLimitSupported(sourceMimetype, targetMimetype, options)
: false;
}
/**
* Returns the limits from this transformer combined with those of the first transformer in the chain.
* If the first transformer is dynamic, the lowest common denominator between all possible first transformers
* are combined.
*/
protected TransformationOptionLimits getLimits(String sourceMimetype, String targetMimetype,
TransformationOptions options)
{
TransformationOptionLimits firstTransformerLimits = null;
TransformationOptionLimits limits = super.getLimits(sourceMimetype, targetMimetype, options);
ContentTransformer firstTransformer = transformers.get(0);
String firstTargetMimetype = intermediateMimetypes.get(0);
if (firstTransformer == null)
{
try
{
parentTransformers.get().push(this);
@SuppressWarnings("deprecation")
List<ContentTransformer> firstTansformers = legacySynchronousTransformClient.getActiveTransformers(
sourceMimetype, -1, firstTargetMimetype, options);
if (!firstTansformers.isEmpty())
{
for (ContentTransformer transformer: firstTansformers)
{
if (transformer instanceof AbstractContentTransformerLimits)
{
TransformationOptionLimits transformerLimits = ((AbstractContentTransformerLimits)transformer).
getLimits(sourceMimetype, firstTargetMimetype, options);
firstTransformerLimits = (firstTransformerLimits == null)
? transformerLimits
: firstTransformerLimits.combineUpper(transformerLimits);
}
}
}
}
finally
{
parentTransformers.get().pop();
}
}
else
{
if (firstTransformer instanceof AbstractContentTransformerLimits)
{
firstTransformerLimits = ((AbstractContentTransformerLimits)firstTransformer).
getLimits(sourceMimetype, firstTargetMimetype, options);
}
}
if (firstTransformerLimits != null)
{
limits = limits.combine(firstTransformerLimits);
}
return limits;
}
/**
* @see org.alfresco.repo.content.transform.AbstractContentTransformer2#transformInternal(org.alfresco.service.cmr.repository.ContentReader, org.alfresco.service.cmr.repository.ContentWriter, org.alfresco.service.cmr.repository.TransformationOptions)
*/
@Override
public void transformInternal(
ContentReader reader,
ContentWriter writer,
TransformationOptions options) throws Exception
{
NodeRef origSourceNodeRef = options.getSourceNodeRef();
try
{
ContentReader currentReader = reader;
Iterator<ContentTransformer> transformerIterator = transformers.iterator();
Iterator<String> intermediateMimetypeIterator = intermediateMimetypes.iterator();
while (transformerIterator.hasNext())
{
ContentTransformer transformer = transformerIterator.next();
// determine the target mimetype. This is the final target if we are on the last transformation
ContentWriter currentWriter = null;
if (!transformerIterator.hasNext())
{
currentWriter = writer;
}
else
{
String nextMimetype = intermediateMimetypeIterator.next();
// make a temp file writer with the correct extension
String sourceExt = getMimetypeService().getExtension(currentReader.getMimetype());
String targetExt = getMimetypeService().getExtension(nextMimetype);
File tempFile = TempFileProvider.createTempFile(
"ComplextTransformer_intermediate_" + sourceExt + "_",
"." + targetExt);
currentWriter = new FileContentWriter(tempFile);
currentWriter.setMimetype(nextMimetype);
}
// transform
if (transformer == null)
{
try
{
parentTransformers.get().push(this);
legacySynchronousTransformClient.transform(currentReader, currentWriter, options);
}
finally
{
parentTransformers.get().pop();
}
}
else
{
transformer.transform(currentReader, currentWriter, options);
}
// Must clear the sourceNodeRef after the first transformation to avoid later
// transformers thinking the intermediate file is the original node. However as
// we put the original sourceNodeRef back at the end of this try block (so that we are
// not changing any data), we must setting the value to null just after the
// transformation. Really only needs to be done after the first transformation
// but doing it every time is simpler and faster.
options.setSourceNodeRef(null);
// move the source on
currentReader = currentWriter.getReader();
}
// done
}
finally
{
options.setSourceNodeRef(origSourceNodeRef);
}
}
public List<String> getIntermediateMimetypes()
{
return Collections.unmodifiableList(intermediateMimetypes);
}
public List<ContentTransformer> getIntermediateTransformers()
{
return Collections.unmodifiableList(transformers);
}
/**
* Returns the transformer properties predefined (hard coded or implied) by this transformer.
*/
@Override
public String getComments(boolean available)
{
StringBuilder sb = new StringBuilder();
sb.append(super.getComments(available));
sb.append("# ");
sb.append(TransformerConfig.CONTENT);
sb.append(getName());
sb.append(TransformerConfig.PIPELINE);
sb.append('=');
Iterator<String> iterator = intermediateMimetypes.iterator();
for (ContentTransformer transformer: transformers)
{
sb.append(transformer != null ? getSimpleName(transformer) : TransformerConfig.ANY);
if (iterator.hasNext())
{
sb.append(TransformerConfig.PIPE);
String mimetype = iterator.next();
if (mimetype != null && mimetype.length() != 0)
{
String extension = getMimetypeService().getExtension(mimetype);
sb.append(extension);
}
sb.append(TransformerConfig.PIPE);
}
}
sb.append('\n');
return sb.toString();
}
}

View File

@@ -1,203 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import java.util.List;
import java.util.Map;
import org.alfresco.api.AlfrescoPublicApi;
import org.alfresco.repo.content.ContentWorker;
import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.TransformationOptions;
/**
* Interface for class that allow content transformation from one mimetype to another.
*
* @author Derek Hulley
*
* @deprecated The RenditionService is being replace by the simpler async RenditionService2.
*/
@Deprecated
@AlfrescoPublicApi
public interface ContentTransformer extends ContentWorker
{
/**
* @deprecated use version with extra sourceSize parameter.
*/
public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options);
/**
* Indicates whether the provided source mimetype can be transformed into the target mimetype with
* the options specified by this content transformer.
*
* @param sourceMimetype the source mimetype
* @param sourceSize the size (bytes) of the source. If negative it is unknown.
* @param targetMimetype the target mimetype
* @param options the transformation options
* @return boolean true if this content transformer can satify the mimetypes and options specified, false otherwise
*/
public boolean isTransformable(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options);
/**
* Sub component of {@link #isTransformable(String, long, String, TransformationOptions)}
* that checks just the mimetypes.
* @param sourceMimetype the source mimetype
* @param targetMimetype the target mimetype
* @param options the transformation options
* @return boolean true if this content transformer can satify the mimetypes, false otherwise
*/
public boolean isTransformableMimetype(String sourceMimetype, String targetMimetype, TransformationOptions options);
/**
* Sub component of {@link #isTransformable(String, long, String, TransformationOptions)}
* that checks just the size limits.
* @param sourceMimetype the source mimetype
* @param sourceSize the size (bytes) of the source. If negative it is unknown.
* @param targetMimetype the target mimetype
* @param options the transformation options
* @return boolean true if this content transformer can satify the mimetypes, false otherwise
*/
public boolean isTransformableSize(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options);
/**
* Overridden to supply a comment or String of commented out transformation properties
* that specify any (hard coded or implied) supported transformations. Used
* when providing a list of properties to an administrators who may be setting
* other transformation properties, via JMX. Consider overriding if
* {link {@link AbstractContentTransformerLimits#isTransformableMimetype(String, String, TransformationOptions)}
* or {@link ContentTransformerWorker#isTransformable(String, String, TransformationOptions)}
* have been overridden.
* @param available indicates if the transformer has been registered and is available to be selected.
* {@code false} indicates that the transformer is only available as a component of a
* complex transformer.
* @return one line per property. The simple transformer name is returned by default as a comment.
*/
public String getComments(boolean available);
/**
* Returns the maximum source size (in KBytes) allowed given the supplied values.
* @return 0 if the the transformation is disabled, -1 if there is no limit, otherwise the size in KBytes.
*/
public long getMaxSourceSizeKBytes(String sourceMimetype, String targetMimetype, TransformationOptions options);
/**
* @deprecated Use transformer priority and unsupported transformer properties.
*
* Indicates whether given the provided transformation parameters this transformer can provide an explicit
* transformation.
*
* 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, 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. Null mimetype values provide the overall value for the transformer.
* <p>
* 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(String sourceMimetype, String targetMimetype);
/**
* @see #transform(ContentReader, ContentWriter, TransformationOptions)
*
* @deprecated
* Deprecated use {link {@link #transform(ContentReader, ContentWriter, TransformationOptions)}.
*/
public void transform(ContentReader reader, ContentWriter writer) throws ContentIOException;
/**
* Transforms the content provided by the reader and source mimetype
* to the writer and target mimetype.
* <p>
* The source and target mimetypes <b>must</b> be available on the
* {@link org.alfresco.service.cmr.repository.ContentAccessor#getMimetype()} methods of
* both the reader and the writer.
* <p>
* Both reader and writer will be closed after the transformation completes.
*
* @param reader the source of the content
* @param writer the destination of the transformed content
* @param options options to pass to the transformer. These are transformer dependent
* and may be null.
* @throws ContentIOException if an IO exception occurs
*
* @deprecated
* Deprecated since 3.0. Options should now be provided as a TransformationOptions object.
*/
@Deprecated
public void transform(
ContentReader reader,
ContentWriter writer,
Map<String, Object> options) throws ContentIOException;
/**
* Transforms the content provided by the reader and source mimetype
* to the writer and target mimetype with the provided transformation options.
* <p>
* The transformation viability can be determined by an up front call
* to {@link #isTransformable(String, String, TransformationOptions)}.
* <p>
* The source and target mimetypes <b>must</b> be available on the
* {@link org.alfresco.service.cmr.repository.ContentAccessor#getMimetype()} methods of
* both the reader and the writer.
* <p>
* Both reader and writer will be closed after the transformation completes.
* <p>
* The provided options can be null.
*
* @param reader the source of the content
* @param contentWriter the destination of the transformed content
* @param options transformation options, these can be null
* @throws ContentIOException if an IO exception occurs
*/
public void transform(ContentReader reader, ContentWriter contentWriter, TransformationOptions options)
throws ContentIOException;
/**
* Returns transformer's name used in configuration.
*/
public String getName();
}

View File

@@ -1,454 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import static org.alfresco.repo.content.transform.TransformerConfig.ANY;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.alfresco.api.AlfrescoPublicApi;
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.
*
* @author dward
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
@AlfrescoPublicApi
public class ContentTransformerHelper implements BeanNameAware
{
private static final Log logger = LogFactory.getLog(ContentTransformerHelper.class);
private MimetypeService mimetypeService;
protected TransformerConfig transformerConfig;
List<DeprecatedSetter> deprecatedSetterMessages;
private static boolean firstDeprecatedSetter = true;
/** The bean name. */
private String beanName;
/**
* Helper setter of the mimetype service. This is not always required.
*
* @param mimetypeService MimetypeService
*/
public void setMimetypeService(MimetypeService mimetypeService)
{
this.mimetypeService = mimetypeService;
}
/**
* @return Returns the mimetype helper
*/
protected MimetypeService getMimetypeService()
{
return mimetypeService;
}
/**
* @deprecated supported transformations are now set with global properties rather than spring configuration.
*/
public void setExplicitTransformations(List<ExplictTransformationDetails> explicitTransformations)
{
deprecatedSupportedTransformations(explicitTransformations, null);
}
/**
* @deprecated supported transformations are now set with global properties rather than spring configuration.
*/
public void setSupportedTransformations(List<SupportedTransformation> supportedTransformations)
{
deprecatedSupportedTransformations(supportedTransformations, "true");
}
/**
* @deprecated supported transformations are now set with global properties rather than spring configuration.
*/
public void setUnsupportedTransformations(List<SupportedTransformation> unsupportedTransformations)
{
deprecatedSupportedTransformations(unsupportedTransformations, "false");
}
public void setTransformerConfig(TransformerConfig transformerConfig)
{
this.transformerConfig = transformerConfig;
}
/**
* Convenience to fetch and check the mimetype for the given content
*
* @param content
* the reader/writer for the content
* @return Returns the mimetype for the content
* @throws AlfrescoRuntimeException
* if the content doesn't have a mimetype
*/
protected String getMimetype(ContentAccessor content)
{
String mimetype = content.getMimetype();
if (mimetype == null)
{
throw new AlfrescoRuntimeException("Mimetype is mandatory for transformation: " + content);
}
// done
return mimetype;
}
/**
* @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)
{
return transformerConfig.getPriority(((ContentTransformer)this), sourceMimetype, targetMimetype) == TransformerConfig.PRIORITY_EXPLICIT;
}
public boolean isSupportedTransformation(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
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(deprecatedSetterMessages);
}
/**
* 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;
}
/**
* Returns the simple form of the transformer name, which has had the normal
* "transformer." prefix to the Spring bean name removed.
*/
public static String getSimpleName(ContentTransformer transformer)
{
String transformerName = transformer.getName();
return transformerName.startsWith(TransformerConfig.TRANSFORMER)
? transformerName.substring(TransformerConfig.TRANSFORMER.length())
: transformerName;
}
/**
* 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 sourceMimetype so that the source extension can be worked out once the mimetypeService
* has been set.
* @param targetMimetype so that the target extension can be worked out once the mimetypeService
* has been set.
* @param suffixAndValue that should be used.
*/
protected void deprecatedSetter(String sourceMimetype, String targetMimetype, String suffixAndValue)
{
if (deprecatedSetterMessages == null)
{
deprecatedSetterMessages = new ArrayList<DeprecatedSetter>();
}
deprecatedSetterMessages.add(new DeprecatedSetter(sourceMimetype, targetMimetype, 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 not set) to replace Spring configuration.
*/
void logDeprecatedSetter(List<DeprecatedSetter> deprecatedSetterMessages)
{
if (deprecatedSetterMessages != null)
{
StringBuilder sb = new StringBuilder();
for (DeprecatedSetter deprecatedSetter: deprecatedSetterMessages)
{
String propertyNameAndValue = deprecatedSetter.getPropertyNameAndValue(beanName);
String propertyName = propertyNameAndValue.replaceAll("=.*", "");
if (transformerConfig.getProperty(propertyName) == null)
{
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);
sb.append(propertyNameAndValue);
sb.append('\n');
}
else
{
logger.warn(propertyNameAndValue+" is set, but spring config still exists");
}
}
deprecatedSetterMessages = null;
if (sb.length() > 0)
{
// Add subsystem's properties anyway (even though an MBean reset would clear them),
// so that existing unit tests work.
transformerConfig.setProperties(sb.toString());
}
}
}
private void deprecatedSupportedTransformations(List<? extends SupportedTransformation> transformations, String value)
{
if (transformations != null)
{
for (SupportedTransformation transformation: transformations)
{
String sourceMimetype = transformation.getSourceMimetype();
String targetMimetype = transformation.getTargetMimetype();
if (value == null)
{
deprecatedSetter(sourceMimetype, targetMimetype, TransformerConfig.PRIORITY+"="+TransformerConfig.PRIORITY_EXPLICIT);
deprecatedSetter(sourceMimetype, targetMimetype, TransformerConfig.SUPPORTED+"=true");
}
else
{
deprecatedSetter(sourceMimetype, targetMimetype, TransformerConfig.SUPPORTED+"="+value);
}
}
}
}
protected String getExtensionOrAny(String mimetype)
{
return mimetype == null || ANY.equals(mimetype) ? ANY : mimetypeService.getExtension(mimetype);
}
public String toString()
{
return getName();
}
/**
* Overridden to supply a comment or String of commented out transformation properties
* that specify any (hard coded or implied) supported transformations. Used
* when providing a list of properties to an administrators who may be setting
* other transformation properties, via JMX. Consider overriding if
* {link {@link AbstractContentTransformerLimits#isTransformableMimetype(String, String, TransformationOptions)}
* or {@link ContentTransformerWorker#isTransformable(String, String, TransformationOptions)}
* have been overridden.
* See {@link #getCommentsOnlySupports(List, List, boolean)} which may be used to help construct a comment.
* @param available indicates if the transformer has been registered and is available to be selected.
* {@code false} indicates that the transformer is only available as a component of a
* complex transformer.
* @return one line per property. The simple transformer name is returned by default as a comment.
*/
public String getComments(boolean available)
{
return getCommentNameAndAvailable(available);
}
/**
* Helper method for {@link #getComments(boolean)} to
* create a line that indicates which source and target mimetypes
* it supports.
* @param available TODO
* @return a String of the form "# only supports xxx, yyy or zzz to aaa or bb\n".
*/
protected String getCommentsOnlySupports(List<String> sourceMimetypes, List<String> targetMimetypes, boolean available)
{
StringBuilder sb = new StringBuilder();
sb.append(getCommentNameAndAvailable(available));
sb.append("# Only supports ");
sb.append(getExtensions(sourceMimetypes));
sb.append(" to ");
sb.append(getExtensions(targetMimetypes));
sb.append("\n");
return sb.toString();
}
/**
* Returns the transformer's simple name and an indication if the transformer is not
* available for selection.
*/
String getCommentNameAndAvailable(boolean available)
{
String name = this instanceof ContentTransformer ? getSimpleName((ContentTransformer)this) : getName();
StringBuilder sb = new StringBuilder();
sb.append(getCommentName(name));
if (!available)
{
sb.append("# ");
sb.append(TransformerConfig.CONTENT);
sb.append(getName());
sb.append(TransformerConfig.AVAILABLE);
sb.append("=false\n");
}
return sb.toString();
}
static String getCommentName(String name)
{
StringBuilder sb = new StringBuilder();
sb.append("# ");
sb.append(name);
sb.append('\n');
sb.append("# ");
for (int i = name.length(); i > 0; i--)
{
sb.append('-');
}
sb.append('\n');
return sb.toString();
}
/**
* Helper method for {@link #getComments(boolean)} to
* create a line that indicates which source and target mimetypes
* it supports.
* @param sourceMimetype String
* @param targetMimetype String
* @param available TODO
* @return a String of the form "# only supports xxx to aaa\n".
*/
protected String onlySupports(String sourceMimetype, String targetMimetype, boolean available)
{
return getCommentsOnlySupports(
Arrays.asList(new String[] {sourceMimetype}),
Arrays.asList(new String[] {targetMimetype}), available);
}
/**
* Returns a comma separated String of mimetype file extensions.
*/
private String getExtensions(List<String> origMimetypes)
{
// Only use the mimetypes we have registered
List<String> mimetypes = new ArrayList<String>(origMimetypes);
mimetypes.retainAll(getMimetypeService().getMimetypes());
StringBuilder sb = new StringBuilder();
int j = mimetypes.size();
int i=1;
for (String mimetype: mimetypes)
{
sb.append(getMimetypeService().getExtension(mimetype));
if (i < j)
{
sb.append(++i < j ? ", " : " or ");
}
}
return sb.toString();
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((beanName == null) ? 0 : beanName.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ContentTransformerHelper other = (ContentTransformerHelper) obj;
if (beanName == null)
{
if (other.beanName != null)
return false;
}
else if (!beanName.equals(other.beanName))
return false;
return true;
}
private class DeprecatedSetter
{
private final String sourceMimetype;
private final String targetMimetype;
private final String suffixAndValue;
DeprecatedSetter(String sourceMimetype, String targetMimetype, String suffixAndValue)
{
this.sourceMimetype = sourceMimetype;
this.targetMimetype = targetMimetype;
this.suffixAndValue = suffixAndValue;
}
public String getPropertyNameAndValue(String beanName)
{
return TransformerConfig.CONTENT+beanName+
(sourceMimetype != null
? TransformerConfig.EXTENSIONS+getExtensionOrAny(sourceMimetype)+'.'+getExtensionOrAny(targetMimetype)
: ".")+
suffixAndValue;
}
}
}

View File

@@ -1,289 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.alfresco.api.AlfrescoPublicApi;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Holds and provides the most appropriate content transformer for
* a particular source and target mimetype transformation request.
* <p>
* The transformers themselves are used to determine the applicability
* of a particular transformation.
* <p>
* The actual selection of a transformer is done by the injected
* {@link TransformerSelector}.
*
* @see org.alfresco.repo.content.transform.ContentTransformer
*
* @author Derek Hulley
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
@AlfrescoPublicApi
public class ContentTransformerRegistry
{
private static final Log logger = LogFactory.getLog(ContentTransformerRegistry.class);
private final List<ContentTransformer> transformers;
private final List<ContentTransformer> allTransformers;
private final TransformerSelector transformerSelector;
private boolean enabled = true;
private boolean firstTime = true;
private TransformerDebug transformerDebug;
/**
* @param transformerSelector Transformer selector
*/
public ContentTransformerRegistry(TransformerSelector transformerSelector)
{
this.transformerSelector = transformerSelector;
this.transformers = new ArrayList<ContentTransformer>(70);
this.allTransformers = new ArrayList<ContentTransformer>(70);
}
public void setEnabled(boolean enabled)
{
this.enabled = enabled;
firstTime = true;
}
public void setTransformerDebug(TransformerDebug transformerDebug)
{
this.transformerDebug = transformerDebug;
}
/**
* Registers an individual transformer that can be queried to check for applicability.
*
* @param transformer a content transformer
*/
public synchronized void addTransformer(ContentTransformer transformer)
{
transformers.add(transformer);
allTransformers.add(transformer);
// done
if (logger.isDebugEnabled())
{
logger.debug("Registered general transformer: \n" +
" transformer: " + transformer.getName() + " (" + transformer + ")");
}
}
/**
* Records a transformer that can NOT be queried for applicability, but may be
* included as a component of complex transformers.
* @param transformer a content transformer
*/
public synchronized void addComponentTransformer(ContentTransformer transformer)
{
allTransformers.add(transformer);
}
/**
* Removes a dynamically created transformer.
* @param transformer to be removed.
*/
public synchronized void removeTransformer(ContentTransformer transformer)
{
transformers.remove(transformer);
allTransformers.remove(transformer);
}
/**
* @return a list of transformers that may be queried to check for applicability.
*/
public synchronized List<ContentTransformer> getTransformers()
{
return Collections.unmodifiableList(transformers);
}
/**
* @return a list of all transformers, including those that only exist as a
* component of another transformer.
*/
public synchronized List<ContentTransformer> getAllTransformers()
{
return Collections.unmodifiableList(allTransformers);
}
/**
* Returns a transformer identified by name.
* @throws IllegalArgumentException if transformerName is not found.
*/
public synchronized ContentTransformer getTransformer(String transformerName)
{
if (transformerName != null)
{
for (ContentTransformer transformer: allTransformers)
{
if (transformerName.equals(transformer.getName()))
{
return transformer;
}
}
throw new IllegalArgumentException("Unknown transformer: "+
(transformerName.startsWith(TransformerConfig.TRANSFORMER)
? transformerName.substring(TransformerConfig.TRANSFORMER.length())
: transformerName));
}
return null;
}
/**
* @deprecated use overloaded version with sourceSize parameter.
*/
public ContentTransformer getTransformer(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
return getTransformer(sourceMimetype, -1, targetMimetype, options);
}
/**
* Gets the best transformer possible. This is a combination of the most reliable
* and the most performant transformer.
*/
public ContentTransformer getTransformer(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options)
{
// Get the sorted list of transformers
List<ContentTransformer> transformers = getActiveTransformers(sourceMimetype, sourceSize, targetMimetype, options);
// select the most performant transformer
ContentTransformer bestTransformer = null;
if(transformers.size() > 0)
{
bestTransformer = transformers.get(0);
}
// done
return bestTransformer;
}
/**
* @since 3.5
*/
public List<ContentTransformer> getActiveTransformers(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options)
{
if (firstTime)
{
firstTime = false;
transformerDebug.debug("Legacy transforms are " + (enabled ? "enabled" : "disabled"));
}
// Get the list of transformers
List<ContentTransformer> transformers;
if (enabled)
{
transformers = transformerSelector.selectTransformers(sourceMimetype, sourceSize, targetMimetype, options);
}
else
{
transformers = Collections.EMPTY_LIST;
}
if (logger.isDebugEnabled())
{
logger.debug("Searched for transformer: \n" +
" source mimetype: " + sourceMimetype + "\n" +
" target mimetype: " + targetMimetype + "\n" +
" transformers: " + transformers);
}
return transformers;
}
/**
* Recursive method to build up a list of content transformers
*/
@SuppressWarnings("unused")
private void buildTransformer(List<ContentTransformer> transformers,
double reliability,
List<String> touchedMimetypes,
String currentMimetype,
String targetMimetype)
{
throw new UnsupportedOperationException();
}
/**
* A key for a combination of a source and target mimetype
*
* Deprecated since 3.0
*/
@Deprecated
public static class TransformationKey
{
private final String sourceMimetype;
private final String targetMimetype;
private final String key;
public TransformationKey(String sourceMimetype, String targetMimetype)
{
this.key = (sourceMimetype + "_" + targetMimetype);
this.sourceMimetype = sourceMimetype;
this.targetMimetype = targetMimetype;
}
public String getSourceMimetype()
{
return sourceMimetype;
}
public String getTargetMimetype()
{
return targetMimetype;
}
@Override
public boolean equals(Object obj)
{
if (obj == null)
{
return false;
}
else if (this == obj)
{
return true;
}
else if (!(obj instanceof TransformationKey))
{
return false;
}
TransformationKey that = (TransformationKey) obj;
return this.key.equals(that.key);
}
@Override
public int hashCode()
{
return key.hashCode();
}
}
}

View File

@@ -1,88 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import org.alfresco.api.AlfrescoPublicApi;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.TransformationOptions;
/**
* An interface that allows separation between the content transformer registry and the various third party subsystems
* performing the transformation.
*
* @author dward
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
// TODO Modify ContentTransformerWorker to understand transformer limits. At the moment no workers use them
@Deprecated
@AlfrescoPublicApi
public interface ContentTransformerWorker
{
/**
* Checks if this worker is available.
*
* @return true if it is available
*/
public boolean isAvailable();
/**
* Gets a string returning product and version information.
*
* @return the version string
*/
public String getVersionString();
/**
* Unlike {@link ContentTransformer#isTransformable(String, String, TransformationOptions)}
* should not include the transformer name, as that is added by the ContentTransformer in
* the parent context.
*/
public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options);
/**
* @see ContentTransformer#getComments(boolean)
*/
public String getComments(boolean available);
/**
* @see ContentTransformer#transform(ContentReader, ContentWriter, TransformationOptions)
*/
public void transform(ContentReader reader, ContentWriter writer, TransformationOptions options) throws Exception;
/**
* @return true if ther worker is using a remote server.
*/
public default boolean remoteTransformerClientConfigured()
{
return false;
}
public default void setRemoteTransformerClient(RemoteTransformerClient remoteTransformerClient)
{
}
}

View File

@@ -1,173 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import java.util.Map;
import java.util.Map.Entry;
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.<p>
*
* Originally created for mapping source and target mimetypes to transformer configuration data.<p>
*
* For example:
* <pre>
* DoubleMap<String, String, String> foodLikes = new DoubleMap<String, String, String>("*", "*");
*
* 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"
* </pre>
*
* @author Alan Davis
*
*/
@Deprecated
public class DoubleMap<K1, K2, V>
{
private final Map<K1, Map<K2, V>> mapMap = new ConcurrentHashMap<K1, Map<K2, V>>();
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<K2, V> 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;
}
/**
* Returns a value for the given keys without using wildcards.
*/
public V getNoWildcards(K1 key1, K2 key2)
{
V value = null;
Map<K2, V> map = mapMap.get(key1);
if (map != null)
{
value = map.get(key2);
}
return value;
}
/**
* Adds a value for the given keys.
*/
public void put(K1 key1, K2 key2, V t)
{
Map<K2, V> map = mapMap.get(key1);
if (map == null)
{
map = new ConcurrentHashMap<K2, V>();
mapMap.put(key1, map);
}
map.put(key2, t);
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder();
for (Entry<K1, Map<K2, V>> outerEntry: mapMap.entrySet())
{
for (Entry<K2, V> innerEntry: outerEntry.getValue().entrySet())
{
if (sb.length() > 0)
{
sb.append("\n");
}
sb.append(outerEntry.getKey()).
append(", ").
append(innerEntry.getKey()).
append(" = ").
append(innerEntry.getValue());
}
}
return sb.toString();
}
}

View File

@@ -1,272 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.content.filestore.FileContentWriter;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.util.TempFileProvider;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.internet.MimeMessage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import static org.alfresco.repo.rendition2.RenditionDefinition2.TARGET_ENCODING;
/**
* Uses javax.mail.MimeMessage to generate plain text versions of RFC822 email
* messages. Searches for all text content parts, and returns them. Any
* attachments are ignored. TIKA Note - could be replaced with the Tika email
* parser. Would require a recursing parser to be specified, but not the full
* Auto one (we don't want attachments), just one containing text and html
* related parsers.
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public class EMLTransformer extends AbstractRemoteContentTransformer
{
private static final Log logger = LogFactory.getLog(EMLTransformer.class);
private static final String CHARSET = "charset";
private static final String DEFAULT_ENCODING = "UTF-8";
@Override
public boolean isTransformableMimetype(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
if (!MimetypeMap.MIMETYPE_RFC822.equals(sourceMimetype)
|| !MimetypeMap.MIMETYPE_TEXT_PLAIN.equals(targetMimetype))
{
// only support RFC822 -> TEXT
return false;
}
else
{
return true;
}
}
@Override
public String getComments(boolean available)
{
return onlySupports(MimetypeMap.MIMETYPE_RFC822, MimetypeMap.MIMETYPE_TEXT_PLAIN, available);
}
@Override
protected Log getLogger()
{
return logger;
}
@Override
protected void transformLocal(ContentReader reader, ContentWriter writer, TransformationOptions options) throws Exception
{
InputStream contentInputStream = null;
try{
contentInputStream = reader.getContentInputStream();
MimeMessage mimeMessage = new MimeMessage(Session.getDefaultInstance(new Properties()), contentInputStream);
final StringBuilder sb = new StringBuilder();
Object content = mimeMessage.getContent();
if (content instanceof Multipart)
{
processMultiPart((Multipart) content,sb);
}
else
{
sb.append(content.toString());
}
writer.putContent(sb.toString());
}
finally
{
if (contentInputStream != null)
{
try
{
contentInputStream.close();
}
catch ( IOException e)
{
//stop exception propagation
}
}
}
}
/**
* Find "text" parts of message recursively and appends it to sb StringBuilder
*
* @param multipart Multipart to process
* @param sb StringBuilder
* @throws MessagingException
* @throws IOException
*/
private void processMultiPart(Multipart multipart, StringBuilder sb) throws MessagingException, IOException
{
boolean isAlternativeMultipart = multipart.getContentType().contains(MimetypeMap.MIMETYPE_MULTIPART_ALTERNATIVE);
if (isAlternativeMultipart)
{
processAlternativeMultipart(multipart, sb);
}
else
{
for (int i = 0, n = multipart.getCount(); i < n; i++)
{
Part part = multipart.getBodyPart(i);
if (part.getContent() instanceof Multipart)
{
processMultiPart((Multipart) part.getContent(), sb);
}
else
{
processPart(part, sb);
}
}
}
}
/**
* Finds the suitable part from an multipart/alternative and appends it's text content to StringBuilder sb
*
* @param multipart
* @param sb
* @throws IOException
* @throws MessagingException
*/
private void processAlternativeMultipart(Multipart multipart, StringBuilder sb) throws IOException, MessagingException
{
Part partToUse = null;
for (int i = 0, n = multipart.getCount(); i < n; i++)
{
Part part = multipart.getBodyPart(i);
if (part.getContentType().contains(MimetypeMap.MIMETYPE_TEXT_PLAIN))
{
partToUse = part;
break;
}
else if (part.getContentType().contains(MimetypeMap.MIMETYPE_HTML))
{
partToUse = part;
}
else if (part.getContentType().contains(MimetypeMap.MIMETYPE_MULTIPART_ALTERNATIVE))
{
if (part.getContent() instanceof Multipart)
{
processAlternativeMultipart((Multipart) part.getContent(), sb);
}
}
}
if (partToUse != null)
{
processPart(partToUse, sb);
}
}
/**
* Finds text on a given mail part. Accepted parts types are text/html and text/plain.
* Attachments are ignored
*
* @param part
* @param sb
* @throws IOException
* @throws MessagingException
*/
private void processPart(Part part, StringBuilder sb) throws IOException, MessagingException
{
boolean isAttachment = Part.ATTACHMENT.equalsIgnoreCase(part.getDisposition());
if (isAttachment)
{
return;
}
if (part.getContentType().contains(MimetypeMap.MIMETYPE_TEXT_PLAIN))
{
sb.append(part.getContent().toString());
}
else if (part.getContentType().contains(MimetypeMap.MIMETYPE_HTML))
{
String mailPartContent = part.getContent().toString();
//create a temporary html file with same mail part content and encoding
File tempHtmlFile = TempFileProvider.createTempFile("EMLTransformer_", ".html");
ContentWriter contentWriter = new FileContentWriter(tempHtmlFile);
contentWriter.setEncoding(getMailPartContentEncoding(part));
contentWriter.setMimetype(MimetypeMap.MIMETYPE_HTML);
contentWriter.putContent(mailPartContent);
//transform html file's content to plain text
EncodingAwareStringBean extractor = new EncodingAwareStringBean();
extractor.setCollapse(false);
extractor.setLinks(false);
extractor.setReplaceNonBreakingSpaces(false);
extractor.setURL(tempHtmlFile, contentWriter.getEncoding());
sb.append(extractor.getStrings());
tempHtmlFile.delete();
}
}
private String getMailPartContentEncoding(Part part) throws MessagingException
{
String encoding = DEFAULT_ENCODING;
String contentType = part.getContentType();
int startIndex = contentType.indexOf(CHARSET);
if (startIndex > 0)
{
encoding = contentType.substring(startIndex + CHARSET.length() + 1).replaceAll("\"", "");
}
return encoding;
}
@Override
protected void transformRemote(RemoteTransformerClient remoteTransformerClient, ContentReader reader,
ContentWriter writer, TransformationOptions options,
String sourceMimetype, String targetMimetype,
String sourceExtension, String targetExtension,
String targetEncoding) throws Exception
{
long timeoutMs = options.getTimeoutMs();
remoteTransformerClient.request(reader, writer, sourceMimetype, sourceExtension, targetExtension,
timeoutMs, logger,
"transformName", "rfc822",
"sourceMimetype", sourceMimetype,
"targetMimetype", targetMimetype,
"targetExtension", targetExtension);
}
}

View File

@@ -1,97 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import java.io.File;
import java.net.URLConnection;
import org.htmlparser.Parser;
import org.htmlparser.beans.StringBean;
import org.htmlparser.util.ParserException;
/**
* A version of {@link StringBean} which allows control of the
* encoding in the underlying HTML Parser.
* Unfortunately, StringBean doesn't allow easy over-riding of
* this, so we have to duplicate some code to control this.
* This allows us to correctly handle HTML files where the encoding
* is specified against the content property (rather than in the
* HTML Head Meta), see ALF-10466 for details.
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
class EncodingAwareStringBean extends StringBean
{
private static final long serialVersionUID = -9033414360428669553L;
/**
* Sets the File to extract strings from, and the encoding
* it's in (if known to Alfresco)
*
* @param file The File that text should be fetched from.
* @param encoding The encoding of the input
*/
public void setURL(File file, String encoding)
{
String previousURL = getURL();
String newURL = file.getAbsolutePath();
if ( (previousURL == null) || (!newURL.equals(previousURL)) )
{
try
{
URLConnection conn = getConnection();
if (null == mParser)
{
mParser = new Parser(newURL);
}
else
{
mParser.setURL(newURL);
}
if (encoding != null)
{
mParser.setEncoding(encoding);
}
mPropertySupport.firePropertyChange(PROP_URL_PROPERTY, previousURL, getURL());
mPropertySupport.firePropertyChange(PROP_CONNECTION_PROPERTY, conn, mParser.getConnection());
setStrings();
}
catch (ParserException pe)
{
updateStrings(pe.toString());
}
}
}
public String getEncoding(){
return mParser.getEncoding();
}
}

View File

@@ -1,47 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
/**
* Specifies transformations that are considered to be 'exceptional' so
* should be used in preference to other transformers that can perform
* the same transformation.
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public class ExplictTransformationDetails extends SupportedTransformation
{
public ExplictTransformationDetails()
{
super();
}
public ExplictTransformationDetails(String sourceMimetype, String targetMimetype)
{
super(sourceMimetype, targetMimetype);
}
}

View File

@@ -1,299 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import java.io.File;
import java.util.List;
import org.alfresco.api.AlfrescoPublicApi;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.content.filestore.FileContentWriter;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.util.TempFileProvider;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
/**
* This class is a transformer which contains a fixed sequence of delegate transformers.
* Requests to transform a document will be passed to the first transformer in the sequence.
* If that transformer successfully transforms the document then the process is complete. However
* should it fail, the transformation will be passed on to the next transformer in the sequence and
* so on.
* <P/>Transformers are considered to have failed of they throw an exception.
*
* @author Neil McErlean
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
@AlfrescoPublicApi
public class FailoverContentTransformer extends AbstractContentTransformer2 implements InitializingBean
{
private static Log logger = LogFactory.getLog(FailoverContentTransformer.class);
private List<ContentTransformer> transformers;
public FailoverContentTransformer()
{
// Intentionally empty
}
/**
* The list of transformers to use. There must be at least one, but for failover behaviour to work
* there should be at least two.
*
* @param transformers list of transformers.
*/
public void setTransformers(List<ContentTransformer> transformers)
{
this.transformers = transformers;
}
/**
* Ensures that required properties have been set
*/
public void afterPropertiesSet() throws Exception
{
if (transformers == null || transformers.size() == 0)
{
throw new AlfrescoRuntimeException("At least one inner transformer must be supplied: " + this);
}
if (getMimetypeService() == null)
{
throw new AlfrescoRuntimeException("'mimetypeService' is a required property");
}
}
/**
* Overrides super class method to avoid calling
* {@link #isTransformableMimetype(String, String, TransformationOptions)}
* twice on each transformer in the list, as
* {@link #isTransformableSize(String, long, String, TransformationOptions)}
* in this class must check the mimetype too.
*/
@Override
public boolean isTransformable(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options)
{
return
isSupportedTransformation(sourceMimetype, targetMimetype, options) &&
// isTransformableSize must check the mimetype anyway
(((sourceSize >= 0) && isTransformableSize(sourceMimetype, sourceSize, targetMimetype, options)) ||
((sourceSize < 0) && isTransformableMimetype(sourceMimetype,targetMimetype, options)));
}
@Override
public boolean isTransformableMimetype(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
return isTransformableMimetypeAndSize(sourceMimetype, -1, targetMimetype, options);
}
@Override
public boolean isTransformableSize(String sourceMimetype, long sourceSize, String targetMimetype, TransformationOptions options)
{
return (sourceSize < 0) ||
super.isTransformableSize(sourceMimetype, sourceSize, targetMimetype, options) &&
isTransformableMimetypeAndSize(sourceMimetype, sourceSize, targetMimetype, options);
}
private boolean isTransformableMimetypeAndSize(String sourceMimetype, long sourceSize,
String targetMimetype, TransformationOptions options)
{
boolean result = false;
for (ContentTransformer ct : this.transformers)
{
if (ct.isTransformableMimetype(sourceMimetype, targetMimetype, options))
{
if (sourceSize < 0)
{
result = true;
break;
}
else
{
try
{
((LegacyTransformerDebug)transformerDebug).pushIsTransformableSize(this);
if (ct.isTransformableSize(sourceMimetype, sourceSize, targetMimetype, options))
{
result = true;
break;
}
}
finally
{
((LegacyTransformerDebug)transformerDebug).popIsTransformableSize();
}
}
}
}
return result;
}
@SuppressWarnings("deprecation")
public boolean isExplicitTransformation(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
boolean result = true;
for (ContentTransformer ct : this.transformers)
{
if (ct.isExplicitTransformation(sourceMimetype, targetMimetype, options) == false)
{
result = false;
}
}
return result;
}
/**
* @see org.alfresco.repo.content.transform.AbstractContentTransformer2#transformInternal(org.alfresco.service.cmr.repository.ContentReader, org.alfresco.service.cmr.repository.ContentWriter, org.alfresco.service.cmr.repository.TransformationOptions)
*/
@Override
public void transformInternal(
ContentReader reader,
ContentWriter writer,
TransformationOptions options) throws Exception
{
final String outputMimetype = writer.getMimetype();
final String outputFileExt = getMimetypeService().getExtension(outputMimetype);
// We need to keep a reference to thrown exceptions as we're going to catch them and
// then move on to the next transformer. In the event that they all fail, we will throw
// the final exception.
Exception transformationException = null;
for (int i = 0; i < transformers.size(); i++)
{
int oneBasedCount = i + 1;
ContentTransformer transf = transformers.get(i);
ContentWriter currentWriter = null;
File tempFile = null;
try
{
if (logger.isDebugEnabled())
{
logger.debug("Transformation attempt " + oneBasedCount + " of " + transformers.size() + ": " + transf);
}
if (!transf.isTransformable(reader.getMimetype(), reader.getSize(), outputMimetype, options))
{
throw new UnsupportedTransformationException("Unsupported transformation: " +reader.getMimetype()+" to "+outputMimetype);
}
// We can't know in advance which transformer in the sequence will work - if any.
// Therefore we can't write into the ContentWriter stream.
// So make a temporary file writer with the current transformer name.
tempFile = TempFileProvider.createTempFile(
"FailoverTransformer_intermediate_" + transf.getClass().getSimpleName() + "_",
"." + outputFileExt);
currentWriter = new FileContentWriter(tempFile);
currentWriter.setMimetype(outputMimetype);
currentWriter.setEncoding(writer.getEncoding());
// attempt to transform
transf.transform(reader, currentWriter, options);
// TODO Could add a check for zero-length output and treat that as a failure
// final long writtenSize = currentWriter.getSize();
}
catch (Exception are)
{
if (transformationException == null)
{
transformationException = are;
}
if (logger.isDebugEnabled())
{
logger.debug("Transformation " + oneBasedCount + " was unsuccessful.");
if (i != transformers.size() - 1)
{
// We don't log the last exception as we're going to throw it.
logger.debug("The below exception is provided for information purposes only.", are);
}
}
// Set a new reader to refresh the input stream.
reader = reader.getReader();
// and move to the next transformer
continue;
}
// No need to close input or output streams
// At this point the current transformation was successful i.e. it did not throw an exception.
// Now we must copy the content from the temporary file into the ContentWriter stream.
if (tempFile != null)
{
writer.putContent(tempFile);
}
if (logger.isInfoEnabled())
{
logger.info("Transformation was successful");
}
return;
}
// At this point we have tried all transformers in the sequence without apparent success.
if (transformationException != null)
{
transformerDebug.debug(" No more transformations to failover to");
if (logger.isDebugEnabled())
{
logger.debug("All transformations were unsuccessful. Throwing first exception.", transformationException);
}
throw transformationException;
}
}
/**
* Returns the transformer properties predefined (hard coded or implied) by this transformer.
*/
@Override
public String getComments(boolean available)
{
StringBuilder sb = new StringBuilder();
sb.append(super.getComments(available));
sb.append("# ");
sb.append(TransformerConfig.CONTENT);
sb.append(getName());
sb.append(TransformerConfig.FAILOVER);
sb.append('=');
boolean first = true;
for (ContentTransformer transformer: transformers)
{
if (!first)
{
sb.append(TransformerConfig.PIPE);
}
first = false;
sb.append(transformer != null ? getSimpleName(transformer) : TransformerConfig.ANY);
}
sb.append('\n');
return sb.toString();
}
}

View File

@@ -1,147 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import java.io.File;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.util.TempFileProvider;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import static org.alfresco.repo.rendition2.RenditionDefinition2.SOURCE_ENCODING;
/**
* Content transformer which wraps the HTML Parser library for
* parsing HTML content.
*
* <p>
* Since HTML Parser was updated from v1.6 to v2.1, META tags
* defining an encoding for the content via http-equiv=Content-Type
* will ONLY be respected if the encoding of the content item
* itself is set to ISO-8859-1.
* </p>
*
* <p>
* Tika Note - could be converted to use the Tika HTML parser,
* but we'd potentially need a custom text handler to replicate
* the current settings around links and non-breaking spaces.
* </p>
*
* @see <a href="http://htmlparser.sourceforge.net/">http://htmlparser.sourceforge.net</a>
* @see org.htmlparser.beans.StringBean
* @see <a href="http://sourceforge.net/tracker/?func=detail&aid=1644504&group_id=24399&atid=381401">HTML Parser</a>
*
* @author Derek Hulley
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public class HtmlParserContentTransformer extends AbstractRemoteContentTransformer
{
@SuppressWarnings("unused")
private static final Log logger = LogFactory.getLog(HtmlParserContentTransformer.class);
/**
* Only support HTML to TEXT.
*/
@Override
public boolean isTransformableMimetype(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
if (!MimetypeMap.MIMETYPE_HTML.equals(sourceMimetype) ||
!MimetypeMap.MIMETYPE_TEXT_PLAIN.equals(targetMimetype))
{
// only support HTML -> TEXT
return false;
}
else
{
return true;
}
}
@Override
public String getComments(boolean available)
{
return onlySupports(MimetypeMap.MIMETYPE_HTML, MimetypeMap.MIMETYPE_TEXT_PLAIN, available);
}
@Override
protected Log getLogger()
{
return logger;
}
@Override
public void transformLocal(ContentReader reader, ContentWriter writer, TransformationOptions options)
throws Exception
{
// We can only work from a file
File htmlFile = TempFileProvider.createTempFile("HtmlParserContentTransformer_", ".html");
reader.getContent(htmlFile);
// Fetch the encoding of the HTML, as set in the ContentReader
// This will default to 'UTF-8' if not specifically set
String encoding = reader.getEncoding();
// Create the extractor
EncodingAwareStringBean extractor = new EncodingAwareStringBean();
extractor.setCollapse(false);
extractor.setLinks(false);
extractor.setReplaceNonBreakingSpaces(false);
extractor.setURL(htmlFile, encoding);
// get the text
String text = extractor.getStrings();
// write it to the writer
writer.putContent(text);
// Tidy up
htmlFile.delete();
}
@Override
protected void transformRemote(RemoteTransformerClient remoteTransformerClient, ContentReader reader,
ContentWriter writer, TransformationOptions options, String sourceMimetype,
String targetMimetype, String sourceExtension, String targetExtension,
String targetEncoding) throws Exception
{
String sourceEncoding = reader.getEncoding();
long timeoutMs = options.getTimeoutMs();
remoteTransformerClient.request(reader, writer, sourceMimetype, sourceExtension, targetExtension,
timeoutMs, logger,
"transformName", "html",
"sourceMimetype", sourceMimetype,
"sourceExtension", sourceExtension,
"targetMimetype", targetMimetype,
SOURCE_ENCODING, sourceEncoding);
}
}

View File

@@ -1,128 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2017 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import org.alfresco.repo.content.JodConverter;
import org.alfresco.util.Pair;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.artofsolving.jodconverter.OfficeDocumentConverter;
import org.artofsolving.jodconverter.document.DocumentFormat;
import org.springframework.beans.factory.InitializingBean;
import java.io.File;
/**
* Makes use of the {@link http://code.google.com/p/jodconverter/} library and an installed
* OpenOffice application to perform OpenOffice-driven conversions.
*
* @author Neil McErlean
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public class JodContentTransformer extends OOoContentTransformerHelper implements ContentTransformerWorker, InitializingBean
{
private static Log logger = LogFactory.getLog(JodContentTransformer.class);
private boolean enabled = true;
private JodConverter jodconverter;
public void setEnabled(boolean enabled)
{
this.enabled = enabled;
}
public void setJodConverter(JodConverter jodc)
{
this.jodconverter = jodc;
}
@Override
protected Log getLogger()
{
return logger;
}
@Override
protected String getTempFilePrefix()
{
return "JodContentTransformer";
}
@Override
public boolean isAvailable()
{
if (remoteTransformerClientConfigured() && !remoteTransformerClient.isAvailable())
{
afterPropertiesSet();
}
return remoteTransformerClientConfigured()
? remoteTransformerClient.isAvailable()
: jodconverter.isAvailable();
}
@Override
public void afterPropertiesSet()
{
if (enabled)
{
super.afterPropertiesSet();
if (remoteTransformerClientConfigured())
{
Pair<Boolean, String> result = remoteTransformerClient.check(logger);
Boolean isAvailable = result.getFirst();
if (isAvailable != null && isAvailable)
{
String versionString = result.getSecond().trim();
logger.debug("Using legacy JodCoverter: " + versionString);
}
else
{
String message = "Legacy JodConverter is not available for transformations. " + result.getSecond();
if (isAvailable == null)
{
logger.debug(message);
}
else
{
logger.error(message);
}
}
}
}
}
@Override
protected void convert(File tempFromFile, DocumentFormat sourceFormat, File tempToFile,
DocumentFormat targetFormat)
{
OfficeDocumentConverter converter = new OfficeDocumentConverter(jodconverter.getOfficeManager());
converter.convert(tempFromFile, tempToFile);
}
}

View File

@@ -1,647 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2019 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import org.alfresco.repo.content.metadata.AsynchronousExtractor;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.transform.client.registry.SupportedTransform;
import org.alfresco.util.PropertyCheck;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Deque;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.TreeSet;
/**
* Debugs Legacy transformers selection and activity. Will be removed when Legacy transforms are removed.
*
* @author Alan Davis
*/
@Deprecated
public class LegacyTransformerDebug extends AdminUiTransformerDebug
{
private ContentTransformerRegistry transformerRegistry;
private TransformerConfig transformerConfig;
public void setTransformerRegistry(ContentTransformerRegistry transformerRegistry)
{
this.transformerRegistry = transformerRegistry;
}
public void setTransformerConfig(TransformerConfig transformerConfig)
{
this.transformerConfig = transformerConfig;
}
@Override
public void afterPropertiesSet() throws Exception
{
super.afterPropertiesSet();
PropertyCheck.mandatory(this, "transformerRegistry", transformerRegistry);
PropertyCheck.mandatory(this, "transformerConfig", transformerConfig);
}
@Deprecated
public void pushAvailable(String fromUrl, String sourceMimetype, String targetMimetype,
TransformationOptions options)
{
String renditionName = options == null ? null : options.getUse();
NodeRef sourceNodeRef = options == null ? null : options.getSourceNodeRef();
pushAvailable(fromUrl, sourceMimetype, targetMimetype, renditionName, sourceNodeRef);
}
/**
* Called prior to working out what transformers are available.
*/
@Deprecated
public void pushAvailable(String fromUrl, String sourceMimetype, String targetMimetype,
String renditionName, NodeRef sourceNodeRef)
{
if (isEnabled())
{
push(null, fromUrl, sourceMimetype, targetMimetype, -1,
null, renditionName, sourceNodeRef, Call.AVAILABLE);
}
}
/**
* Called when a transformer has been ignored because of a blacklist entry.
*/
@Deprecated
public void blacklistTransform(ContentTransformer transformer, String sourceMimetype,
String targetMimetype, TransformationOptions options)
{
log("Blacklist "+getName(transformer)+" "+ getSourceAndTargetExt(sourceMimetype, targetMimetype));
}
@Deprecated
public void pushTransform(ContentTransformer transformer, String fromUrl, String sourceMimetype,
String targetMimetype, long sourceSize, TransformationOptions options)
{
String renditionName = options == null ? null : options.getUse();
NodeRef sourceNodeRef = options == null ? null : options.getSourceNodeRef();
pushTransform(transformer, fromUrl, sourceMimetype, targetMimetype, sourceSize, renditionName, sourceNodeRef);
}
/**
* Called prior to performing a transform.
*/
@Deprecated
public void pushTransform(ContentTransformer transformer, String fromUrl, String sourceMimetype,
String targetMimetype, long sourceSize, String renditionName, NodeRef sourceNodeRef)
{
if (isEnabled())
{
push(getName(transformer), fromUrl, sourceMimetype, targetMimetype, sourceSize,
null, renditionName, sourceNodeRef, Call.TRANSFORM);
}
}
/**
* Called prior to calling a nested isTransformable.
*/
@Deprecated
public void pushIsTransformableSize(ContentTransformer transformer)
{
if (isEnabled())
{
ThreadInfo.getIsTransformableStack().push(getName(transformer));
}
}
/**
* Called to identify a transformer that cannot be used during working out
* available transformers.
*/
@Deprecated
public void unavailableTransformer(ContentTransformer transformer, String sourceMimetype, String targetMimetype, long maxSourceSizeKBytes)
{
if (isEnabled())
{
Deque<Frame> ourStack = ThreadInfo.getStack();
Frame frame = ourStack.peek();
if (frame != null)
{
Deque<String> isTransformableStack = ThreadInfo.getIsTransformableStack();
String name = (!isTransformableStack.isEmpty())
? isTransformableStack.getFirst()
: getName(transformer);
boolean debug = (maxSourceSizeKBytes != 0);
if (frame.unavailableTransformers == null)
{
frame.unavailableTransformers = new TreeSet<UnavailableTransformer>();
}
String priority = gePriority(transformer, sourceMimetype, targetMimetype);
frame.unavailableTransformers.add(new UnavailableTransformer(name, priority, maxSourceSizeKBytes, debug));
}
}
}
@Deprecated
public void availableTransformers(List<ContentTransformer> transformers, long sourceSize,
TransformationOptions options, String calledFrom)
{
String renditionName = options == null ? null : options.getUse();
NodeRef sourceNodeRef = options == null ? null : options.getSourceNodeRef();
availableTransformers(transformers, sourceSize, renditionName, sourceNodeRef, calledFrom);
}
/**
* Called once all available transformers have been identified.
*/
@Deprecated
public void availableTransformers(List<ContentTransformer> transformers, long sourceSize,
String renditionName, NodeRef sourceNodeRef, String calledFrom)
{
if (isEnabled())
{
Deque<Frame> ourStack = ThreadInfo.getStack();
Frame frame = ourStack.peek();
boolean firstLevel = ourStack.size() == 1;
// Override setDebugOutput(false) to allow debug when there are transformers but they are all unavailable
// Note once turned on we don't turn it off again.
if (transformers.size() == 0)
{
frame.setFailureReason(NO_TRANSFORMERS);
if (frame.unavailableTransformers != null &&
frame.unavailableTransformers.size() != 0)
{
ThreadInfo.setDebugOutput(true);
}
}
frame.setSourceSize(sourceSize);
// Log the basic info about this transformation
logBasicDetails(frame, sourceSize, null, renditionName,
calledFrom + ((transformers.size() == 0) ? " NO transformers" : ""), firstLevel);
// Report available and unavailable transformers
char c = 'a';
int longestNameLength = getLongestTransformerNameLength(transformers, frame);
for (ContentTransformer trans : transformers)
{
String name = getName(trans);
int padName = longestNameLength - name.length() + 1;
TransformationOptions options = new TransformationOptions();
options.setUse(frame.renditionName);
options.setSourceNodeRef(frame.sourceNodeRef);
long maxSourceSizeKBytes = trans.getMaxSourceSizeKBytes(frame.sourceMimetype, frame.targetMimetype, options);
String size = maxSourceSizeKBytes > 0 ? "< "+fileSize(maxSourceSizeKBytes*1024) : "";
int padSize = 10 - size.length();
String priority = gePriority(trans, frame.sourceMimetype, frame.targetMimetype);
log((c == 'a' ? "**" : " ") + (c++) + ") " + priority + ' ' + name + spaces(padName) +
size + spaces(padSize) + ms(trans.getTransformationTime(frame.sourceMimetype, frame.targetMimetype)));
}
if (frame.unavailableTransformers != null)
{
for (UnavailableTransformer unavailable: frame.unavailableTransformers)
{
int pad = longestNameLength - unavailable.name.length();
String reason = "> "+fileSize(unavailable.maxSourceSizeKBytes*1024);
if (unavailable.debug || logger.isTraceEnabled())
{
log("--" + (c++) + ") " + unavailable.priority + ' ' + unavailable.name + spaces(pad+1) + reason, unavailable.debug);
}
}
}
}
}
private String gePriority(ContentTransformer transformer, String sourceMimetype, String targetMimetype)
{
String priority =
'[' + (isComponentTransformer(transformer)
? "---"
: Integer.toString(transformerConfig.getPriority(transformer, sourceMimetype, targetMimetype))) +
']';
priority = spaces(5-priority.length())+priority;
return priority;
}
@Deprecated
public void inactiveTransformer(ContentTransformer transformer)
{
log(getName(transformer)+' '+ms(transformer.getTransformationTime(null, null))+" INACTIVE");
}
@Deprecated
public void activeTransformer(int mimetypePairCount, ContentTransformer transformer, String sourceMimetype,
String targetMimetype, long maxSourceSizeKBytes, boolean firstMimetypePair)
{
if (firstMimetypePair)
{
log(getName(transformer)+' '+ms(transformer.getTransformationTime(sourceMimetype, targetMimetype)));
}
String i = Integer.toString(mimetypePairCount);
String priority = gePriority(transformer, sourceMimetype, targetMimetype);
String sourceExt = getMimetypeExt(sourceMimetype);
String targetExt = getMimetypeExt(targetMimetype);
targetExt = AsynchronousExtractor.getExtension(targetMimetype, sourceExt, targetExt);
log(spaces(5-i.length())+mimetypePairCount+") "+ sourceExt + targetExt +
priority +
' '+fileSize((maxSourceSizeKBytes > 0) ? maxSourceSizeKBytes*1024 : maxSourceSizeKBytes)+
(maxSourceSizeKBytes == 0 ? " disabled" : ""));
}
@Deprecated
public void activeTransformer(String sourceMimetype, String targetMimetype,
int transformerCount, ContentTransformer transformer, long maxSourceSizeKBytes,
boolean firstTransformer)
{
String priority = gePriority(transformer, sourceMimetype, targetMimetype);
activeTransformer(sourceMimetype, targetMimetype, transformerCount, priority, getName(transformer),
maxSourceSizeKBytes, firstTransformer);
}
private int getLongestTransformerNameLength(List<ContentTransformer> transformers,
Frame frame)
{
int longestNameLength = 0;
for (ContentTransformer trans : transformers)
{
int length = getName(trans).length();
if (longestNameLength < length)
longestNameLength = length;
}
if (frame != null && frame.unavailableTransformers != null)
{
for (UnavailableTransformer unavailable: frame.unavailableTransformers)
{
int length = unavailable.name.length();
if (longestNameLength < length)
longestNameLength = length;
}
}
return longestNameLength;
}
/**
* Called after working out what transformers are available and any
* resulting transform has been called.
*/
public void popAvailable()
{
if (isEnabled())
{
pop(Call.AVAILABLE, false, false);
}
}
/**
* Called after returning from a nested isTransformable.
*/
public void popIsTransformableSize()
{
if (isEnabled())
{
ThreadInfo.getIsTransformableStack().pop();
}
}
/**
* Returns a String and /or debug that provides a list of supported transformations for each
* transformer.
* @param transformerName restricts the list to one transformer. Unrestricted if null.
* @param toString indicates that a String value should be returned in addition to any debug.
* @param format42 indicates the old 4.1.4 format should be used which did not order the transformers
* and only included top level transformers.
* @param renditionName to which the transformation will be put (such as "Index", "Preview", null).
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public String transformationsByTransformer(String transformerName, boolean toString, boolean format42, String renditionName)
{
// Do not generate this type of debug if already generating other debug to a StringBuilder
// (for example a test transform).
if (getStringBuilder() != null)
{
return null;
}
Collection<ContentTransformer> transformers = format42 || transformerName != null
? sortTransformersByName(transformerName)
: transformerRegistry.getTransformers();
Collection<String> sourceMimetypes = format42
? getSourceMimetypes(null)
: mimetypeService.getMimetypes();
Collection<String> targetMimetypes = format42
? sourceMimetypes
: mimetypeService.getMimetypes();
TransformationOptions options = new TransformationOptions();
options.setUse(renditionName);
StringBuilder sb = null;
try
{
if (toString)
{
sb = new StringBuilder();
setStringBuilder(sb);
}
pushMisc();
for (ContentTransformer transformer: transformers)
{
try
{
pushMisc();
int mimetypePairCount = 0;
boolean first = true;
for (String sourceMimetype: sourceMimetypes)
{
for (String targetMimetype: targetMimetypes)
{
if (transformer.isTransformable(sourceMimetype, -1, targetMimetype, options))
{
long maxSourceSizeKBytes = transformer.getMaxSourceSizeKBytes(
sourceMimetype, targetMimetype, options);
activeTransformer(++mimetypePairCount, transformer,
sourceMimetype, targetMimetype, maxSourceSizeKBytes, first);
first = false;
}
}
}
if (first)
{
inactiveTransformer(transformer);
}
}
finally
{
popMisc();
}
}
}
finally
{
popMisc();
setStringBuilder(null);
}
stripFinishedLine(sb);
return stripLeadingNumber(sb);
}
/**
* Returns a String and /or debug that provides a list of supported transformations
* sorted by source and target mimetype extension.
* @param sourceExtension restricts the list to one source extension. Unrestricted if null.
* @param targetExtension restricts the list to one target extension. Unrestricted if null.
* @param toString indicates that a String value should be returned in addition to any debug.
* @param format42 indicates the new 4.2 rather than older 4.1.4 format should be used.
* The 4.1.4 format did not order the transformers or mimetypes and only included top
* level transformers.
* @param onlyNonDeterministic if true only report transformations where there is more than
* one transformer available with the same priority.
* @param renditionName to which the transformation will be put (such as "Index", "Preview", null).
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
@Override
public String transformationsByExtension(String sourceExtension, String targetExtension, boolean toString,
boolean format42, boolean onlyNonDeterministic, String renditionName)
{
// Do not generate this type of debug if already generating other debug to a StringBuilder
// (for example a test transform).
if (getStringBuilder() != null)
{
return null;
}
Collection<ContentTransformer> transformers = format42 && !onlyNonDeterministic
? sortTransformersByName(null)
: transformerRegistry.getTransformers();
Collection<String> sourceMimetypes = format42 || sourceExtension != null
? getSourceMimetypes(sourceExtension)
: mimetypeService.getMimetypes();
Collection<String> targetMimetypes = format42 || targetExtension != null
? getTargetMimetypes(sourceExtension, targetExtension, sourceMimetypes)
: mimetypeService.getMimetypes();
TransformationOptions options = new TransformationOptions();
options.setUse(renditionName);
StringBuilder sb = null;
try
{
if (toString)
{
sb = new StringBuilder();
setStringBuilder(sb);
}
pushMisc();
for (String sourceMimetype: sourceMimetypes)
{
for (String targetMimetype: targetMimetypes)
{
// Find available transformers
List<ContentTransformer> availableTransformer = new ArrayList<ContentTransformer>();
for (ContentTransformer transformer: transformers)
{
if (transformer.isTransformable(sourceMimetype, -1, targetMimetype, options))
{
availableTransformer.add(transformer);
}
}
// Sort by priority
final String currSourceMimetype = sourceExtension;
final String currTargetMimetype = targetExtension;
Collections.sort(availableTransformer, new Comparator<ContentTransformer>()
{
@Override
public int compare(ContentTransformer transformer1, ContentTransformer transformer2)
{
return transformerConfig.getPriority(transformer1, currSourceMimetype, currTargetMimetype) -
transformerConfig.getPriority(transformer2, currSourceMimetype, currTargetMimetype);
}
});
// Do we need to produce any output?
int size = availableTransformer.size();
int priority = size >= 2
? transformerConfig.getPriority(availableTransformer.get(0), sourceMimetype, targetMimetype)
: -1;
if (!onlyNonDeterministic || (size >= 2 && priority ==
transformerConfig.getPriority(availableTransformer.get(1), sourceMimetype, targetMimetype)))
{
// Log the transformers
boolean supportedByTransformService = remoteTransformServiceRegistry == null ||
remoteTransformServiceRegistry instanceof DummyTransformServiceRegistry
? false
: remoteTransformServiceRegistry.isSupported(sourceMimetype,
-1, targetMimetype, Collections.emptyMap(), null);
List<SupportedTransform> localTransformers = localTransformServiceRegistryImpl == null
? Collections.emptyList()
: localTransformServiceRegistryImpl.findTransformers(sourceMimetype,
targetMimetype, Collections.emptyMap(), null);
if (!localTransformers.isEmpty() || supportedByTransformService || size >= 1)
{
try
{
pushMisc();
int transformerCount = 0;
if (supportedByTransformService)
{
long maxSourceSizeKBytes = remoteTransformServiceRegistry.findMaxSize(sourceMimetype,
targetMimetype, Collections.emptyMap(), null);
activeTransformer(sourceMimetype, targetMimetype, transformerCount, " ",
TRANSFORM_SERVICE_NAME, maxSourceSizeKBytes, transformerCount++ == 0);
}
for (SupportedTransform localTransformer : localTransformers)
{
long maxSourceSizeKBytes = localTransformer.getMaxSourceSizeBytes();
String transformName = "Local:" + localTransformer.getName();
String transformerPriority = "[" + localTransformer.getPriority() + ']';
transformerPriority = spaces(5-transformerPriority.length())+transformerPriority;
activeTransformer(sourceMimetype, targetMimetype, transformerCount, transformerPriority,
transformName, maxSourceSizeKBytes, transformerCount++ == 0);
}
for (ContentTransformer transformer: availableTransformer)
{
if (!onlyNonDeterministic || transformerCount < 2 ||
priority == transformerConfig.getPriority(transformer, sourceMimetype, targetMimetype))
{
long maxSourceSizeKBytes = transformer.getMaxSourceSizeKBytes(
sourceMimetype, targetMimetype, options);
activeTransformer(sourceMimetype, targetMimetype, transformerCount,
transformer, maxSourceSizeKBytes, transformerCount++ == 0);
}
}
}
finally
{
popMisc();
}
}
}
}
}
}
finally
{
popMisc();
setStringBuilder(null);
}
stripFinishedLine(sb);
return stripLeadingNumber(sb);
}
private String getName(ContentTransformer transformer)
{
String name =
transformer instanceof ContentTransformerHelper
? ContentTransformerHelper.getSimpleName(transformer)
: transformer.getClass().getSimpleName();
String type =
((transformer instanceof AbstractRemoteContentTransformer &&
((AbstractRemoteContentTransformer)transformer).remoteTransformerClientConfigured()) ||
(transformer instanceof ProxyContentTransformer &&
((ProxyContentTransformer)transformer).remoteTransformerClientConfigured())
? "Remote" : "")+
(transformer instanceof ComplexContentTransformer
? "Complex"
: transformer instanceof FailoverContentTransformer
? "Failover"
: transformer instanceof ProxyContentTransformer
? (((ProxyContentTransformer)transformer).getWorker() instanceof RuntimeExecutableContentTransformerWorker)
? "Runtime"
: "Proxy"
: "");
boolean componentTransformer = isComponentTransformer(transformer);
StringBuilder sb = new StringBuilder("Legacy:").append(name);
if (componentTransformer || type.length() > 0)
{
sb.append("<<");
sb.append(type);
if (componentTransformer)
{
sb.append("Component");
}
sb.append(">>");
}
return sb.toString();
}
private boolean isComponentTransformer(ContentTransformer transformer)
{
return !transformerRegistry.getTransformers().contains(transformer);
}
@Deprecated
public String getFileName(TransformationOptions options, boolean firstLevel, long sourceSize)
{
NodeRef sourceNodeRef = options == null ? null : options.getSourceNodeRef();
return getFileName(sourceNodeRef, firstLevel, sourceSize);
}
/**
* Returns a sorted list of all transformers sorted by name.
* @param transformerName to restrict the collection to one entry
* @return a new Collection of sorted transformers
* @throws IllegalArgumentException if transformerName is not found.
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public Collection<ContentTransformer> sortTransformersByName(String transformerName)
{
Collection<ContentTransformer> transformers = (transformerName != null)
? Collections.singleton(transformerRegistry.getTransformer(transformerName))
: transformerRegistry.getAllTransformers();
SortedMap<String, ContentTransformer> map = new TreeMap<String, ContentTransformer>();
for (ContentTransformer transformer: transformers)
{
String name = transformer.getName();
map.put(name, transformer);
}
Collection<ContentTransformer> sorted = map.values();
return sorted;
}
/**
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public String testTransform(final String transformerName, String sourceExtension,
String targetExtension, String renditionName)
{
logger.error("The testTransform operation for a specific transformer is no longer supported. " +
"Request redirected to the version of this method without a transformerName.");
return testTransform(sourceExtension, targetExtension, renditionName);
}
}

View File

@@ -180,7 +180,7 @@ public class LocalTransformImpl extends AbstractLocalTransform
}
// These 3 values are commonly needed and are always supplied in the TransformRequest (message to the T-Router).
// The targetExtension is also supplied in the TransformRequest, but in the case of local and legacy transformers
// The targetExtension is also supplied in the TransformRequest, but in the case of local transforms
// is added by the remoteTransformerClient.request call for historic reasons, so does not need to be added here.
args[i++] = "sourceMimetype";
args[i++] = sourceMimetype;

View File

@@ -484,9 +484,7 @@ public class LocalTransformServiceRegistry extends TransformServiceRegistryImpl
transformerDebug.debug("Local transforms "+getData()+" are " + (enabled ? "enabled" : "disabled"));
}
return enabled
? super.findMaxSize(sourceMimetype, targetMimetype, options, renditionName)
: 0;
return super.findMaxSize(sourceMimetype, targetMimetype, options, renditionName);
}
public LocalTransform getLocalTransform(String sourceMimetype, long sourceSizeInBytes, String targetMimetype, Map<String, String> actualOptions, String renditionName)
@@ -495,9 +493,14 @@ public class LocalTransformServiceRegistry extends TransformServiceRegistryImpl
{
return null;
}
LocalTransform localTransform = null;
String name = findTransformerName(sourceMimetype, sourceSizeInBytes, targetMimetype, actualOptions, renditionName);
LocalData data = getData();
Map<String, LocalTransform> localTransforms = data.localTransforms;
return localTransforms.get(name);
if (name != null)
{
LocalData data = getData();
Map<String, LocalTransform> localTransforms = data.localTransforms;
localTransform = localTransforms.get(name);
}
return localTransform;
}
}

View File

@@ -29,10 +29,7 @@ import org.apache.commons.logging.Log;
/**
* Interface that gives access to Log entries
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
interface LogEntries extends Log
{
/**

View File

@@ -1,55 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import org.alfresco.repo.content.MimetypeMap;
import org.apache.tika.parser.Parser;
import org.apache.tika.parser.microsoft.OfficeParser;
/**
* Uses <a href="http://tika.apache.org/">Apache Tika</a> and
* <a href="@link http://poi.apache.org/">Apache POI</a> to transform
* Outlook email msg files.
*
* @author Nick Burch
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public class MailContentTransformer extends TikaPoweredContentTransformer
{
public MailContentTransformer() {
super(new String[] {
MimetypeMap.MIMETYPE_OUTLOOK_MSG
});
setTransformerName("OutlookMsg");
}
@Override
protected Parser getParser() {
return new OfficeParser();
}
}

View File

@@ -1,179 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import info.bliki.wiki.filter.Encoder;
import info.bliki.wiki.model.WikiModel;
import info.bliki.wiki.tags.ATag;
import java.util.Arrays;
import java.util.List;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.htmlcleaner.ContentToken;
/**
* MediaWiki content transformer. Converts mediawiki markup into HTML.
*
* <br>@see <a href="http://matheclipse.org/en/Java_Wikipedia_API">Java_Wikipedia_API</a>
*
* Tika Note - Tika doesn't currently support mediawiki markup, so this
* transformer cannot currently be converted to use Tika.
*
* @author Roy Wetherall
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public class MediaWikiContentTransformer extends AbstractContentTransformer2
{
/** The file folder service */
private FileFolderService fileFolderService;
/** The node service */
private NodeService nodeService;
/**
* Sets the file folder service
*
* @param fileFolderService the file folder service
*/
public void setFileFolderService(FileFolderService fileFolderService)
{
this.fileFolderService = fileFolderService;
}
/**
* Sets the node service
*
* @param nodeService the node service
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* Only transform from mediawiki to html
*
* @see org.alfresco.repo.content.transform.ContentTransformer#isTransformable(java.lang.String, java.lang.String, org.alfresco.service.cmr.repository.TransformationOptions)
*/
@Override
public boolean isTransformableMimetype(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
if (!MimetypeMap.MIMETYPE_TEXT_MEDIAWIKI.equals(sourceMimetype) ||
!MimetypeMap.MIMETYPE_HTML.equals(targetMimetype))
{
// only support MEDIAWIKI -> HTML
return false;
}
else
{
return true;
}
}
@Override
public String getComments(boolean available)
{
return onlySupports(MimetypeMap.MIMETYPE_TEXT_MEDIAWIKI, MimetypeMap.MIMETYPE_HTML, available);
}
/**
* @see org.alfresco.repo.content.transform.AbstractContentTransformer2#transformInternal(org.alfresco.service.cmr.repository.ContentReader, org.alfresco.service.cmr.repository.ContentWriter, org.alfresco.service.cmr.repository.TransformationOptions)
*/
public void transformInternal(ContentReader reader, ContentWriter writer, TransformationOptions options)
throws Exception
{
String imageURL = "{$image}";
String pageURL = "${title}";
// If we have context about the destination of the transformation then use it
if (options.getTargetNodeRef() != null)
{
NodeRef parentNodeRef = this.nodeService.getPrimaryParent(options.getTargetNodeRef()).getParentRef();
StringBuffer folderPath = new StringBuffer(256);
List<FileInfo> fileInfos = this.fileFolderService.getNamePath(null, parentNodeRef);
for (FileInfo fileInfo : fileInfos)
{
folderPath.append(fileInfo.getName()).append("/");
}
pageURL = "/alfresco/d/d?path=" + folderPath + "${title}.html";
imageURL = "/alfresco/d/d?path=" + folderPath + "Images/${image}";
}
// Create the wikiModel and set the title and image link URL's
AlfrescoWikiModel wikiModel = new AlfrescoWikiModel(imageURL, pageURL);
// Render the wiki content as HTML
writer.putContent(wikiModel.render(reader.getContentString()));
}
/**
* Alfresco custom Wiki model used to generate links and image references
*
* @author Roy Wetherall
*/
private class AlfrescoWikiModel extends WikiModel
{
public AlfrescoWikiModel(String imageBaseURL, String linkBaseURL)
{
super(imageBaseURL, linkBaseURL);
}
@Override
public void appendInternalLink(String link, String hashSection, String linkText)
{
link = link.replaceAll(":", " - ");
String encodedtopic = Encoder.encodeTitleUrl(link);
encodedtopic = encodedtopic.replaceAll("_", " ");
String hrefLink = fExternalWikiBaseURL.replace("${title}", encodedtopic);
ATag aTagNode = new ATag();
append(aTagNode);
aTagNode.addAttribute("id", "w");
String href = hrefLink;
if (hashSection != null) {
href = href + '#' + hashSection;
}
aTagNode.addAttribute("href", href);
aTagNode.addObjectAttribute("wikilink", hrefLink);
ContentToken text = new ContentToken(linkText);
aTagNode.addChild(text);
}
}
}

View File

@@ -1,164 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.util.TempFileProvider;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
import org.apache.poi.openxml4j.opc.PackageRelationshipTypes;
/**
* Extracts out Thumbnail JPEGs from OOXML files for thumbnailing & previewing.
* This transformer will only work for OOXML files where thumbnailing was enabled,
* which isn't on by default on Windows, but is more common on Mac.
*
* @author Nick Burch
* @since 4.0.1
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public class OOXMLThumbnailContentTransformer extends AbstractContentTransformer2
{
public static final String NO_THUMBNAIL_PRESENT_IN_FILE = "No thumbnail present in file, unable to generate ";
private static final Log log = LogFactory.getLog(OOXMLThumbnailContentTransformer.class);
private static final List<String> OOXML_MIMETYPES = Arrays.asList(new String[]{
MimetypeMap.MIMETYPE_OPENXML_WORDPROCESSING,
MimetypeMap.MIMETYPE_OPENXML_WORDPROCESSING_MACRO,
MimetypeMap.MIMETYPE_OPENXML_WORD_TEMPLATE,
MimetypeMap.MIMETYPE_OPENXML_WORD_TEMPLATE_MACRO,
MimetypeMap.MIMETYPE_OPENXML_PRESENTATION,
MimetypeMap.MIMETYPE_OPENXML_PRESENTATION_MACRO,
MimetypeMap.MIMETYPE_OPENXML_PRESENTATION_SLIDESHOW,
MimetypeMap.MIMETYPE_OPENXML_PRESENTATION_SLIDESHOW_MACRO,
MimetypeMap.MIMETYPE_OPENXML_PRESENTATION_TEMPLATE,
MimetypeMap.MIMETYPE_OPENXML_PRESENTATION_TEMPLATE_MACRO,
MimetypeMap.MIMETYPE_OPENXML_PRESENTATION_ADDIN,
MimetypeMap.MIMETYPE_OPENXML_PRESENTATION_SLIDE,
MimetypeMap.MIMETYPE_OPENXML_PRESENTATION_SLIDE_MACRO,
MimetypeMap.MIMETYPE_OPENXML_SPREADSHEET,
MimetypeMap.MIMETYPE_OPENXML_SPREADSHEET_TEMPLATE,
MimetypeMap.MIMETYPE_OPENXML_SPREADSHEET_MACRO,
MimetypeMap.MIMETYPE_OPENXML_SPREADSHEET_TEMPLATE_MACRO,
MimetypeMap.MIMETYPE_OPENXML_SPREADSHEET_ADDIN_MACRO,
MimetypeMap.MIMETYPE_OPENXML_SPREADSHEET_BINARY_MACRO});
private static final List<String> TARGET_MIMETYPES = Arrays.asList(new String[]{MimetypeMap.MIMETYPE_IMAGE_JPEG});
@Override
public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
// only support [OOXML] -> JPEG
return TARGET_MIMETYPES.contains(targetMimetype) && OOXML_MIMETYPES.contains(sourceMimetype);
}
@Override
public String getComments(boolean available)
{
StringBuilder sb = new StringBuilder();
sb.append(super.getComments(available));
sb.append("# Only supports extraction of embedded jpegs from OOXML formats\n");
return sb.toString();
}
@Override
protected void transformInternal(ContentReader reader,
ContentWriter writer,
TransformationOptions options) throws Exception
{
final String sourceMimetype = reader.getMimetype();
final String sourceExtension = getMimetypeService().getExtension(sourceMimetype);
final String targetMimetype = writer.getMimetype();
if (log.isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Transforming from ").append(sourceMimetype)
.append(" to ").append(targetMimetype);
log.debug(msg.toString());
}
OPCPackage pkg = null;
try
{
File ooxmlTempFile = TempFileProvider.createTempFile(this.getClass().getSimpleName() + "_ooxml", sourceExtension);
reader.getContent(ooxmlTempFile);
// Load the file
pkg = OPCPackage.open(ooxmlTempFile.getPath());
// Does it have a thumbnail?
PackageRelationshipCollection rels =
pkg.getRelationshipsByType(PackageRelationshipTypes.THUMBNAIL);
if (rels.size() > 0)
{
// Get the thumbnail part
PackageRelationship tRel = rels.getRelationship(0);
PackagePart tPart = pkg.getPart(tRel);
// Write it to the target
InputStream tStream = tPart.getInputStream();
writer.putContent( tStream );
tStream.close();
}
else
{
log.debug("No thumbnail present in " + reader.toString());
throw new UnimportantTransformException(NO_THUMBNAIL_PRESENT_IN_FILE + targetMimetype);
}
}
catch (IOException e)
{
throw new AlfrescoRuntimeException("Unable to transform " + sourceExtension + " file.", e);
}
finally
{
if (pkg != null)
{
pkg.close();
}
}
}
}

View File

@@ -1,503 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import com.sun.star.task.ErrorCodeIOException;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.repository.ContentIOException;
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.alfresco.util.TempFileProvider;
import org.apache.commons.logging.Log;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.artofsolving.jodconverter.document.*;
import org.artofsolving.jodconverter.office.OfficeException;
import org.json.JSONException;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.util.FileCopyUtils;
import java.io.*;
/**
* A class providing basic OOo-related functionality shared by both
* {@link ContentTransformer}s and {@link ContentTransformerWorker}s.
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public abstract class OOoContentTransformerHelper extends ContentTransformerHelper
{
private String documentFormatsConfiguration;
private DocumentFormatRegistry formatRegistry;
protected LegacyTransformerDebug transformerDebug;
private static final int JODCONVERTER_TRANSFORMATION_ERROR_CODE = 3088;
protected RemoteTransformerClient remoteTransformerClient;
/**
* Set a non-default location from which to load the document format mappings.
*
* @param path
* a resource location supporting the <b>file:</b> or <b>classpath:</b> prefixes
*/
public void setDocumentFormatsConfiguration(String path)
{
this.documentFormatsConfiguration = path;
}
protected abstract Log getLogger();
protected abstract String getTempFilePrefix();
public abstract boolean isAvailable();
protected abstract void convert(File tempFromFile, DocumentFormat sourceFormat, File tempToFile,
DocumentFormat targetFormat);
/**
* Helper setter of the transformer debug.
* @param transformerDebug TransformerDebug
*/
public void setTransformerDebug(LegacyTransformerDebug transformerDebug)
{
this.transformerDebug = transformerDebug;
}
/**
* Sets the optional remote transformer client which will be used in preference to a local command if available.
*
* @param remoteTransformerClient may be null;
*/
public void setRemoteTransformerClient(RemoteTransformerClient remoteTransformerClient)
{
this.remoteTransformerClient = remoteTransformerClient;
}
public boolean remoteTransformerClientConfigured()
{
return remoteTransformerClient != null && remoteTransformerClient.getBaseUrl() != null;
}
public void afterPropertiesSet()
{
// load the document conversion configuration
if (formatRegistry == null)
{
if (documentFormatsConfiguration != null)
{
DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
try
{
InputStream is = resourceLoader.getResource(this.documentFormatsConfiguration).getInputStream();
formatRegistry = new JsonDocumentFormatRegistry(is);
// We do not need to explicitly close this InputStream as it is closed for us within the XmlDocumentFormatRegistry
}
catch (IOException e)
{
throw new AlfrescoRuntimeException(
"Unable to load document formats configuration file: "
+ this.documentFormatsConfiguration);
}
catch (JSONException e)
{
throw new AlfrescoRuntimeException(
"Unable to read document formats configuration file: "
+ this.documentFormatsConfiguration);
}
}
else
{
formatRegistry = new DefaultDocumentFormatRegistry();
}
}
}
/**
* There are some conversions that fail, despite the converter believing them possible.
* This method can be used by subclasses to check if a targetMimetype or source/target
* Mimetype pair are blocked.
*
* @param sourceMimetype String
* @param targetMimetype String
* @return <code>true</code> if the mimetypes are blocked, else <code>false</code>
*/
protected boolean isTransformationBlocked(String sourceMimetype, String targetMimetype)
{
if (targetMimetype.equals(MimetypeMap.MIMETYPE_XHTML))
{
return true;
}
else if (targetMimetype.equals(MimetypeMap.MIMETYPE_WORDPERFECT))
{
return true;
}
else if (targetMimetype.equals(MimetypeMap.MIMETYPE_FLASH))
{
return true;
}
else
{
return false;
}
}
/**
* @see DocumentFormatRegistry
*/
public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
// Use BinaryPassThroughContentTransformer if mimetypes are the same.
if (sourceMimetype.equals(targetMimetype))
{
return false;
}
if (!isAvailable())
{
// The connection management is must take care of this
return false;
}
if (isTransformationBlocked(sourceMimetype, targetMimetype))
{
if (getLogger().isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("Transformation from ")
.append(sourceMimetype).append(" to ")
.append(targetMimetype)
.append(" is blocked and therefore unavailable.");
getLogger().debug(msg.toString());
}
return false;
}
MimetypeService mimetypeService = getMimetypeService();
String sourceExtension = mimetypeService.getExtension(sourceMimetype);
String targetExtension = mimetypeService.getExtension(targetMimetype);
// query the registry for the source format
DocumentFormat sourceFormat = formatRegistry.getFormatByExtension(sourceExtension);
if (sourceFormat == null)
{
// no document format
return false;
}
// query the registry for the target format
DocumentFormat targetFormat = formatRegistry.getFormatByExtension(targetExtension);
if (targetFormat == null)
{
// no document format
return false;
}
// get the family of the target document
DocumentFamily sourceFamily = sourceFormat.getInputFamily();
// does the format support the conversion
boolean transformable = formatRegistry.getOutputFormats(sourceFamily).contains(targetFormat); // same as: targetFormat.getStoreProperties(sourceFamily) != null
return transformable;
}
@Override
public String getComments(boolean available)
{
return "# Transformations supported by OpenOffice/LibreOffice\n";
}
/**
* This method produces an empty PDF file at the specified File location.
* Apache's PDFBox is used to create the PDF file.
*/
private void produceEmptyPdfFile(File tempToFile)
{
// If improvement PDFBOX-914 is incorporated, we can do this with a straight call to
// org.apache.pdfbox.TextToPdf.createPDFFromText(new StringReader(""));
// https://issues.apache.org/jira/browse/PDFBOX-914
PDDocument pdfDoc = null;
PDPageContentStream contentStream = null;
try
{
pdfDoc = new PDDocument();
PDPage pdfPage = new PDPage();
// Even though, we want an empty PDF, some libs (e.g. PDFRenderer) object to PDFs
// that have literally nothing in them. So we'll put a content stream in it.
contentStream = new PDPageContentStream(pdfDoc, pdfPage);
pdfDoc.addPage(pdfPage);
// Now write the in-memory PDF document into the temporary file.
pdfDoc.save(tempToFile.getAbsolutePath());
}
catch (IOException iox)
{
throw new ContentIOException("Error creating empty PDF file", iox);
}
finally
{
if (contentStream != null)
{
try
{
contentStream.close();
}
catch (IOException ignored)
{
// Intentionally empty
}
}
if (pdfDoc != null)
{
try
{
pdfDoc.close();
}
catch (IOException ignored)
{
// Intentionally empty.
}
}
}
}
/*
* (non-Javadoc)
* @see org.alfresco.repo.content.transform.ContentTransformerWorker#getVersionString()
*/
public String getVersionString()
{
return "";
}
public void transform(
ContentReader reader,
ContentWriter writer,
TransformationOptions options) throws Exception
{
if (isAvailable() == false)
{
throw new ContentIOException("Content conversion failed (unavailable): \n" +
" reader: " + reader + "\n" +
" writer: " + writer);
}
if (getLogger().isDebugEnabled())
{
StringBuilder msg = new StringBuilder();
msg.append("transforming content from ")
.append(reader.getMimetype())
.append(" to ")
.append(writer.getMimetype());
getLogger().debug(msg.toString());
}
String sourceMimetype = getMimetype(reader);
String targetMimetype = getMimetype(writer);
MimetypeService mimetypeService = getMimetypeService();
String sourceExtension = mimetypeService.getExtension(sourceMimetype);
String targetExtension = mimetypeService.getExtension(targetMimetype);
// query the registry for the source format
DocumentFormat sourceFormat = formatRegistry.getFormatByExtension(sourceExtension);
if (sourceFormat == null)
{
// source format is not recognised
throw new ContentIOException("No OpenOffice document format for source extension: " + sourceExtension);
}
// query the registry for the target format
DocumentFormat targetFormat = formatRegistry.getFormatByExtension(targetExtension);
if (targetFormat == null)
{
// target format is not recognised
throw new ContentIOException("No OpenOffice document format for target extension: " + targetExtension);
}
// get the family of the target document
DocumentFamily sourceFamily = sourceFormat.getInputFamily();
// does the format support the conversion
if (!formatRegistry.getOutputFormats(sourceFamily).contains(targetFormat)) // same as: targetFormat.getStoreProperties(sourceFamily) == null
{
throw new ContentIOException(
"OpenOffice conversion not supported: \n" +
" reader: " + reader + "\n" +
" writer: " + writer);
}
// There is a bug (reported in ALF-219) whereby JooConverter (the Alfresco Community Edition's 3rd party
// OpenOffice connector library) struggles to handle zero-size files being transformed to pdf.
// For zero-length .html files, it throws NullPointerExceptions.
// For zero-length .txt files, it produces a pdf transformation, but it is not a conformant
// pdf file and cannot be viewed (contains no pages).
//
// For these reasons, if the file is of zero length, we will not use JooConverter & OpenOffice
// and will instead ask Apache PDFBox to produce an empty pdf file for us.
final long documentSize = reader.getSize();
if (documentSize == 0L || temporaryMsFile(options))
{
File tempToFile = TempFileProvider.createTempFile(
getTempFilePrefix()+"-target-",
"." + targetExtension);
produceEmptyPdfFile(tempToFile);
writer.putContent(tempToFile);
}
else
{
if (remoteTransformerClientConfigured())
{
transformRemote(reader, writer, options, sourceMimetype, sourceExtension, targetMimetype, targetExtension);
}
else
{
transformLocal(reader, writer, options, sourceMimetype,
sourceExtension, targetExtension, sourceFormat, targetFormat);
}
}
if (getLogger().isDebugEnabled())
{
getLogger().debug("transformation successful");
}
}
protected void transformLocal(ContentReader reader, ContentWriter writer, TransformationOptions options,
String sourceMimetype, String sourceExtension, String targetExtension,
DocumentFormat sourceFormat, DocumentFormat targetFormat)
{
// create temporary files to convert from and to
File tempFromFile = TempFileProvider.createTempFile(
getTempFilePrefix()+"-source-",
"." + sourceExtension);
File tempToFile = TempFileProvider.createTempFile(
getTempFilePrefix()+"-target-",
"." + targetExtension);
// download the content from the source reader
saveContentInFile(sourceMimetype, reader, tempFromFile);
try
{
convert(tempFromFile, sourceFormat, tempToFile, targetFormat);
writer.putContent(tempToFile);
}
catch (OfficeException e)
{
throw new ContentIOException("OpenOffice server conversion failed: \n" +
" reader: " + reader + "\n" +
" writer: " + writer + "\n" +
" from file: " + tempFromFile + "\n" +
" to file: " + tempToFile,
e);
}
catch (Throwable throwable)
{
// Because of the known bug with empty Spreadsheets in JodConverter try to catch exception and produce empty pdf file
if (throwable.getCause() instanceof ErrorCodeIOException &&
((ErrorCodeIOException) throwable.getCause()).ErrCode == JODCONVERTER_TRANSFORMATION_ERROR_CODE)
{
getLogger().warn("Transformation failed: \n" +
"from file: " + tempFromFile + "\n" +
"to file: " + tempToFile +
"Source file " + tempFromFile + " has no content");
produceEmptyPdfFile(tempToFile);
}
else
{
throw throwable;
}
}
}
protected void transformRemote(ContentReader reader, ContentWriter writer, TransformationOptions options,
String sourceMimetype, String sourceExtension,
String targetMimetype, String targetExtension) throws IllegalAccessException
{
long timeoutMs = options.getTimeoutMs();
Log logger = getLogger();
remoteTransformerClient.request(reader, writer, sourceMimetype, sourceExtension, targetExtension,
timeoutMs, logger,
"transformName", "libreoffice",
"sourceMimetype", sourceMimetype,
"sourceExtension", sourceExtension,
"targetMimetype", targetMimetype);
}
private boolean temporaryMsFile(TransformationOptions options)
{
String fileName = transformerDebug == null ? null : transformerDebug.getFileName(options, true, -1);
return fileName != null && fileName.startsWith("~$");
}
/**
* Populates a file with the content in the reader.
*/
public void saveContentInFile(String sourceMimetype, ContentReader reader, File file) throws ContentIOException
{
String encoding = reader.getEncoding();
if (encodeAsUtf8(sourceMimetype, encoding))
{
saveContentInUtf8File(reader, file);
}
else
{
reader.getContent(file);
}
}
/**
* Returns {@code true} if the input file should be transformed to UTF8 encoding.<p>
*
* OpenOffice/LibreOffice is unable to support the import of text files that are SHIFT JIS encoded
* (and others: windows-1252...) so transformed to UTF-8.
*/
protected boolean encodeAsUtf8(String sourceMimetype, String encoding)
{
return MimetypeMap.MIMETYPE_TEXT_PLAIN.equals(sourceMimetype) && !"UTF-8".equals(encoding);
}
/**
* Populates a file with the content in the reader, but also converts the encoding to UTF-8.
*/
private void saveContentInUtf8File(ContentReader reader, File file)
{
String encoding = reader.getEncoding();
try
{
Reader in = new InputStreamReader(reader.getContentInputStream(), encoding);
Writer out = new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream(file)), "UTF-8");
FileCopyUtils.copy(in, out); // both streams are closed
}
catch (IOException e)
{
throw new ContentIOException("Failed to copy content to file and convert "+encoding+" to UTF-8: \n" +
" file: " + file,
e);
}
}
}

View File

@@ -1,127 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.Parser;
import org.apache.tika.parser.pdf.PDFParser;
import org.apache.tika.parser.pdf.PDFParserConfig;
import static org.alfresco.repo.rendition2.RenditionDefinition2.TARGET_ENCODING;
/**
* Uses <a href="http://tika.apache.org/">Apache Tika</a> and
* <a href="@link http://pdfbox.apache.org/">Apache PDFBox</a> to perform
* conversions from PDF documents.
*
* @author Nick Burch
* @author Derek Hulley
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public class PdfBoxContentTransformer extends TikaPoweredContentTransformer
{
/**
* The logger
*/
private static Log logger = LogFactory.getLog(PdfBoxContentTransformer.class);
protected PDFParserConfig pdfParserConfig;
private boolean extractBookmarksText = true;
public PdfBoxContentTransformer() {
super(new String[] {
MimetypeMap.MIMETYPE_PDF
});
}
@Override
protected Parser getParser() {
return new PDFParser();
}
/**
* Sets the PDFParserConfig for inclusion in the ParseContext sent to the PDFBox parser,
* useful for setting config like spacingTolerance.
*
* @param pdfParserConfig
*/
public void setPdfParserConfig(PDFParserConfig pdfParserConfig)
{
this.pdfParserConfig = pdfParserConfig;
}
public void setExtractBookmarksText(boolean extractBookmarksText)
{
this.extractBookmarksText = extractBookmarksText;
}
@Override
protected ParseContext buildParseContext(Metadata metadata, String targetMimeType, TransformationOptions options)
{
ParseContext context = super.buildParseContext(metadata, targetMimeType, options);
if (pdfParserConfig != null)
{
pdfParserConfig.setExtractBookmarksText(extractBookmarksText);
context.set(PDFParserConfig.class, pdfParserConfig);
}
// TODO: Possibly extend TransformationOptions to allow for per-transform PDFParserConfig?
return context;
}
@Override
protected void transformRemote(RemoteTransformerClient remoteTransformerClient, ContentReader reader,
ContentWriter writer, TransformationOptions options,
String sourceMimetype, String targetMimetype,
String sourceExtension, String targetExtension,
String targetEncoding) throws Exception
{
long timeoutMs = options.getTimeoutMs();
String notExtractBookmarksText = null;
if (!extractBookmarksText)
{
notExtractBookmarksText = Boolean.TRUE.toString();
}
remoteTransformerClient.request(reader, writer, sourceMimetype, sourceExtension, targetExtension,
timeoutMs, logger,
"transformName", "PdfBox",
"notExtractBookmarksText", notExtractBookmarksText,
"sourceMimetype", sourceMimetype,
"targetMimetype", targetMimetype,
"targetExtension", targetExtension,
TARGET_ENCODING, targetEncoding);
}
}

View File

@@ -1,80 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import java.util.ArrayList;
import org.alfresco.repo.content.MimetypeMap;
import org.apache.tika.mime.MediaType;
import org.apache.tika.parser.Parser;
import org.apache.tika.parser.microsoft.OfficeParser;
/**
* Uses <a href="http://tika.apache.org/">Apache Tika</a> and
* <a href="@link http://poi.apache.org/">Apache POI</a> to perform
* conversions from Office documents.
*
* {@link PoiHssfContentTransformer} handles the Excel
* transformations (mostly for compatibility), while
* this does all the other Office file formats.
*
* @author Nick Burch
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public class PoiContentTransformer extends TikaPoweredContentTransformer
{
/**
* We support all the office mimetypes that the Tika
* office parser can handle, except for excel
* (handled by {@link PoiHssfContentTransformer}
*/
public static ArrayList<String> SUPPORTED_MIMETYPES;
static {
SUPPORTED_MIMETYPES = new ArrayList<String>();
Parser p = new OfficeParser();
for(MediaType mt : p.getSupportedTypes(null)) {
if(mt.toString().equals(MimetypeMap.MIMETYPE_EXCEL))
{
// Skip, handled elsewhere
continue;
}
// Tika can probably do some useful text
SUPPORTED_MIMETYPES.add( mt.toString() );
}
}
public PoiContentTransformer() {
super(SUPPORTED_MIMETYPES);
setTransformerName("Office");
}
@Override
protected Parser getParser() {
return new OfficeParser();
}
}

View File

@@ -1,215 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import java.io.Writer;
import java.util.regex.Pattern;
import javax.xml.transform.TransformerConfigurationException;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.content.TikaOfficeDetectParser;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tika.parser.Parser;
import org.apache.tika.sax.BodyContentHandler;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
/**
* Uses <a href="http://tika.apache.org/">Apache Tika</a> and
* <a href="@link http://poi.apache.org/">Apache POI</a> to perform
* conversions from Excel spreadsheets.
* <p>Will transform from Excel spreadsheets into Html,
* Xml or Text (space or comma separated)
* <p>Handles all sheets in the file.
*
* @author Nick Burch
* @author Derek Hulley
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public class PoiHssfContentTransformer extends TikaPoweredContentTransformer
{
/**
* Error message to delegate to NodeInfoBean
*/
public static final String WRONG_FORMAT_MESSAGE_ID = "transform.err.format_or_password";
private static Log logger = LogFactory.getLog(PoiHssfContentTransformer.class);
public PoiHssfContentTransformer()
{
super(new String[] {
MimetypeMap.MIMETYPE_EXCEL,
MimetypeMap.MIMETYPE_OPENXML_SPREADSHEET
});
setTransformerName("Poi");
}
@Override
protected Parser getParser()
{
return new TikaOfficeDetectParser();
}
/**
* Can we do the requested transformation via Tika?
* We support transforming to HTML, XML, Text or CSV
*/
@Override
public boolean isTransformableMimetype(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
if(sourceMimeTypes.contains(sourceMimetype) &&
MimetypeMap.MIMETYPE_TEXT_CSV.equals(targetMimetype))
{
// Special case for CSV
return true;
}
// Otherwise fall back on the default Tika rules
return super.isTransformableMimetype(sourceMimetype, targetMimetype, options);
}
/**
* Make sure we win over openoffice when it comes to producing
* HTML
*/
@Override
public boolean isExplicitTransformation(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
if(sourceMimeTypes.contains(sourceMimetype) &&
(MimetypeMap.MIMETYPE_HTML.equals(targetMimetype) ||
MimetypeMap.MIMETYPE_XHTML.equals(targetMimetype)) )
{
// Special case to win for HTML
return true;
}
// Otherwise fall back on the default Tika rules
return super.isTransformableMimetype(sourceMimetype, targetMimetype, options);
}
@Override
protected ContentHandler getContentHandler(String targetMimeType, Writer output)
throws TransformerConfigurationException
{
if(MimetypeMap.MIMETYPE_TEXT_CSV.equals(targetMimeType))
{
return new CsvContentHandler(output);
}
// Otherwise use the normal Tika rules
return super.getContentHandler(targetMimeType, output);
}
/**
* A wrapper around the normal Tika BodyContentHandler,
* which causes things to be CSV encoded rather than
* tab separated
*/
protected static class CsvContentHandler extends BodyContentHandler {
private static final char[] comma = new char[]{ ',' };
private static final Pattern all_nums = Pattern.compile("[\\d\\.\\-\\+]+");
private boolean inCell = false;
private boolean needsComma = false;
protected CsvContentHandler(Writer output) {
super(output);
}
@Override
public void ignorableWhitespace(char[] ch, int start, int length)
throws SAXException {
if(length == 1 && ch[0] == '\t') {
// Ignore tabs, as they mess up the CSV output
} else {
super.ignorableWhitespace(ch, start, length);
}
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
if(inCell) {
StringBuffer t = new StringBuffer(new String(ch,start,length));
// Quote if not all numbers
if(all_nums.matcher(t).matches())
{
super.characters(ch, start, length);
}
else
{
for(int i=t.length()-1; i>=0; i--) {
if(t.charAt(i) == '\"') {
// Double up double quotes
t.insert(i, '\"');
i--;
}
}
t.insert(0, '\"');
t.append('\"');
char[] c = t.toString().toCharArray();
super.characters(c, 0, c.length);
}
} else {
super.characters(ch, start, length);
}
}
@Override
public void startElement(String uri, String localName, String name,
Attributes atts) throws SAXException {
if(localName.equals("td")) {
inCell = true;
if(needsComma) {
super.characters(comma, 0, 1);
needsComma = true;
}
} else {
super.startElement(uri, localName, name, atts);
}
}
@Override
public void endElement(String uri, String localName, String name)
throws SAXException {
if(localName.equals("td")) {
needsComma = true;
inCell = false;
} else {
if(localName.equals("tr")) {
needsComma = false;
}
super.endElement(uri, localName, name);
}
}
}
}

View File

@@ -1,69 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import java.util.ArrayList;
import org.apache.tika.mime.MediaType;
import org.apache.tika.parser.Parser;
import org.apache.tika.parser.microsoft.ooxml.OOXMLParser;
/**
* Uses <a href="http://tika.apache.org/">Apache Tika</a> and
* <a href="@link http://poi.apache.org/">Apache POI</a> to perform
* conversions from the newer OOXML Office documents.
*
* @author Nick Burch
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public class PoiOOXMLContentTransformer extends TikaPoweredContentTransformer
{
/**
* We support all the office mimetypes that the Tika
* office parser can handle
*/
public static ArrayList<String> SUPPORTED_MIMETYPES;
static {
SUPPORTED_MIMETYPES = new ArrayList<String>();
Parser p = new OOXMLParser();
for(MediaType mt : p.getSupportedTypes(null)) {
SUPPORTED_MIMETYPES.add( mt.toString() );
}
}
public PoiOOXMLContentTransformer() {
super(SUPPORTED_MIMETYPES);
setUseTimeoutThread(true);
setTransformerName("OOXML");
}
@Override
protected Parser getParser() {
return new OOXMLParser();
}
}

View File

@@ -1,122 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import org.artofsolving.jodconverter.document.DocumentFormatRegistry;
import org.alfresco.api.AlfrescoPublicApi;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.TransformationOptionLimits;
import org.alfresco.service.cmr.repository.TransformationOptions;
/**
* Makes use of a {@link ContentTransformerWorker} to perform conversions.
*
* @author dward
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
@AlfrescoPublicApi
public class ProxyContentTransformer extends AbstractContentTransformer2
{
private ContentTransformerWorker worker;
public ProxyContentTransformer()
{
}
/**
* @param worker
* the worker that the converter uses
*/
public void setWorker(ContentTransformerWorker worker)
{
this.worker = worker;
}
/**
* Returns the worker that the converter uses
*/
public ContentTransformerWorker getWorker()
{
return this.worker;
}
/**
* THIS IS A CUSTOM SPRING INIT METHOD
*/
public void register()
{
if (worker instanceof ContentTransformerHelper)
{
logDeprecatedSetter(((ContentTransformerHelper)worker).deprecatedSetterMessages);
}
super.register();
}
/**
* @see DocumentFormatRegistry
*/
@Override
public boolean isTransformableMimetype(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
return this.worker.isTransformable(sourceMimetype, targetMimetype, options);
}
@Override
public String getComments(boolean available)
{
StringBuilder sb = new StringBuilder();
sb.append(super.getComments(available));
sb.append(worker.getComments(false));
return sb.toString();
}
protected void transformInternal(ContentReader reader, ContentWriter writer, TransformationOptions options)
throws Exception
{
TransformationOptionLimits original = options.getLimits();
try
{
// Combine the transformer's limit values into the options so they are available to the worker
options.setLimits(getLimits(reader, writer, options));
// Perform the transformation
this.worker.transform(reader, writer, options);
}
finally
{
options.setLimits(original);
}
}
boolean remoteTransformerClientConfigured()
{
return worker.remoteTransformerClientConfigured();
}
}

View File

@@ -1,301 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.api.AlfrescoPublicApi;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.util.TempFileProvider;
import org.alfresco.util.exec.RuntimeExec;
import org.alfresco.util.exec.RuntimeExec.ExecutionResult;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
/**
* This configurable wrapper is able to execute any command line transformation that
* accepts an input and an output file on the command line.
* <p>
* The following parameters are use:
* <ul>
* <li><b>{@link #VAR_SOURCE target}</b> - full path to the source file</li>
* <li><b>{@link #VAR_TARGET source}</b> - full path to the target file</li>
* </ul>
* Provided that the command executed ultimately transforms the source file
* and leaves the result in the target file, the transformation should be
* successful.
* <p>
* <b>NOTE</b>: It is only the contents of the files that can be transformed.
* Any attempt to modify the source or target file metadata will, at best, have
* no effect, but may ultimately lead to the transformation failing. This is
* because the files provided are both temporary files that reside in a location
* outside the system's content store.
* <p>
* This transformer <b>requires</b> the setting of the <b>explicitTransformations</b>
* property.
*
* @see org.alfresco.util.exec.RuntimeExec
*
* @since 1.1
* @author Derek Hulley
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
@AlfrescoPublicApi
public class RuntimeExecutableContentTransformerWorker extends ContentTransformerHelper implements ContentTransformerWorker, InitializingBean
{
public static final String VAR_SOURCE = "source";
public static final String VAR_TARGET = "target";
public static final String VAR_PAGE_RANGE = "pageRange";
private static Log logger = LogFactory.getLog(RuntimeExecutableContentTransformerWorker.class);
private boolean available;
private RuntimeExec checkCommand;
private RuntimeExec transformCommand;
/** Stores the output from the check command */
private String versionString;
public RuntimeExecutableContentTransformerWorker()
{
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append(this.getClass().getSimpleName())
.append("[ transform=").append(transformCommand).append("\n")
.append("]");
return sb.toString();
}
/**
* Set the runtime executer that will be called as part of the initialisation
* to determine if the transformer is able to function. This is optional, but allows
* the transformer registry to detect and avoid using this instance if it is not working.
* <p>
* The command will be considered to have failed if the
*
* @param checkCommand the initialisation check command
*/
public void setCheckCommand(RuntimeExec checkCommand)
{
this.checkCommand = checkCommand;
}
/**
* Set the runtime executer that will called to perform the actual transformation.
*
* @param transformCommand the runtime transform command
*/
public void setTransformCommand(RuntimeExec transformCommand)
{
this.transformCommand = transformCommand;
}
/**
* A comma or space separated list of values that, if returned by the executed command,
* indicate an error value. This defaults to <b>"1, 2"</b>.
*
* @param errCodesStr String
*/
public void setErrorCodes(String errCodesStr)
{
throw new AlfrescoRuntimeException("content.runtime_exec.property_moved");
}
/**
* Executes the check command, if present. Any errors will result in this component
* being rendered unusable within the transformer registry, but may still be called
* directly.
*/
public void afterPropertiesSet()
{
if (transformCommand == null)
{
throw new AlfrescoRuntimeException("Mandatory property 'transformCommand' not set");
}
// execute the command
if (checkCommand != null)
{
ExecutionResult result = checkCommand.execute();
// check the return code
if (this.available = result.getSuccess())
{
this.versionString = result.getStdOut().trim();
}
else
{
logger.error("Failed to start a runtime executable content transformer: \n" + result);
}
}
else
{
// no check - just assume it is available
available = true;
}
}
/**
* If the initialization failed, then it returns 0.0.
* Otherwise the explicit transformations are checked for the reliability.
*
* @return Returns 1.0 if initialization succeeded, otherwise 0.0.
*
* @see AbstractContentTransformer#setExplicitTransformations(List)
*/
public boolean isTransformable(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
return isAvailable();
}
@Override
public String getComments(boolean available)
{
return "";
}
/**
* Signals whether this transformer is available.
*
* @return true, if is available
*/
public boolean isAvailable()
{
return this.available;
}
/**
* Gets the version string captured from the check command.
*
* @return the version string
*/
public String getVersionString()
{
return this.versionString;
}
/**
* Converts the source and target content to temporary files with the
* correct extensions for the mimetype that they map to.
*
*/
public final void transform(
ContentReader reader,
ContentWriter writer,
TransformationOptions options) throws Exception
{
// get mimetypes
String sourceMimetype = getMimetype(reader);
String targetMimetype = getMimetype(writer);
// get the extensions to use
String sourceExtension = getMimetypeService().getExtension(sourceMimetype);
String targetExtension = getMimetypeService().getExtension(targetMimetype);
if (sourceExtension == null || targetExtension == null)
{
throw new AlfrescoRuntimeException("Unknown extensions for mimetypes: \n" +
" source mimetype: " + sourceMimetype + "\n" +
" source extension: " + sourceExtension + "\n" +
" target mimetype: " + targetMimetype + "\n" +
" target extension: " + targetExtension);
}
// create required temp files
File sourceFile = TempFileProvider.createTempFile(
getClass().getSimpleName() + "_source_",
"." + sourceExtension);
File targetFile = TempFileProvider.createTempFile(
getClass().getSimpleName() + "_target_",
"." + targetExtension);
Map<String, String> properties = new HashMap<String, String>(5);
// copy options over
Map<String, Object> optionsMap = options.toMap();
for (Map.Entry<String, Object> entry : optionsMap.entrySet())
{
String key = entry.getKey();
Object value = entry.getValue();
properties.put(key, (value == null ? null : value.toString()));
}
// add the source and target properties
properties.put(VAR_SOURCE, sourceFile.getAbsolutePath());
properties.put(VAR_TARGET, targetFile.getAbsolutePath());
properties.put(VAR_PAGE_RANGE, "0-"+(options.getPageLimit() >=0 ? options.getPageLimit() : ""));
// pull reader file into source temp file
reader.getContent(sourceFile);
// execute the transformation command
long timeoutMs = options.getTimeoutMs();
ExecutionResult result = null;
try
{
result = transformCommand.execute(properties, timeoutMs);
}
catch (Throwable e)
{
throw new ContentIOException("Transformation failed during command execution: \n" + transformCommand, e);
}
// check
if (!result.getSuccess())
{
throw new ContentIOException("Transformation failed - status indicates an error: \n" + result);
}
// check that the file was created
if (!targetFile.exists())
{
throw new ContentIOException("Transformation failed - target file doesn't exist: \n" + result);
}
// copy the target file back into the repo
writer.putContent(targetFile);
// done
if (logger.isDebugEnabled())
{
logger.debug("Transformation completed: \n" +
" source: " + reader + "\n" +
" target: " + writer + "\n" +
" options: " + options + "\n" +
" result: \n" + result);
}
}
}

View File

@@ -1,196 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import static org.alfresco.repo.rendition2.RenditionDefinition2.SOURCE_ENCODING;
import static org.alfresco.repo.rendition2.RenditionDefinition2.TARGET_ENCODING;
/**
* Converts any textual format to plain text.
* <p>
* The transformation is sensitive to the source and target string encodings.
*
* @author Derek Hulley
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public class StringExtractingContentTransformer extends AbstractRemoteContentTransformer
{
public static final String PREFIX_TEXT = "text/";
private static final Log logger = LogFactory.getLog(StringExtractingContentTransformer.class);
/**
* Gives a high reliability for all translations from <i>text/sometype</i> to
* <i>text/plain</i>. As the text formats are already text, the characters
* are preserved and no actual conversion takes place.
* <p>
* Extraction of text from binary data is wholly unreliable.
*/
@Override
public boolean isTransformableMimetype(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
if (!targetMimetype.equals(MimetypeMap.MIMETYPE_TEXT_PLAIN))
{
// can only convert to plain text
return false;
}
else if (sourceMimetype.equals(MimetypeMap.MIMETYPE_TEXT_PLAIN) ||
sourceMimetype.equals(MimetypeMap.MIMETYPE_JAVASCRIPT))
{
// conversions from any plain text format are very reliable
return true;
}
else if (sourceMimetype.startsWith(PREFIX_TEXT) ||
sourceMimetype.equals(MimetypeMap.MIMETYPE_DITA))
{
// the source is text, but probably with some kind of markup
return true;
}
else
{
// extracting text from binary is not useful
return false;
}
}
@Override
public String getComments(boolean available)
{
StringBuilder sb = new StringBuilder();
sb.append(super.getComments(available));
sb.append("# Only supports transformation of js, dita and mimetypes starting with \"");
sb.append(PREFIX_TEXT);
sb.append("\" to txt.\n");
return sb.toString();
}
@Override
protected Log getLogger()
{
return logger;
}
/**
* Text to text conversions are done directly using the content reader and writer string
* manipulation methods.
* <p>
* Extraction of text from binary content attempts to take the possible character
* encoding into account. The text produced from this will, if the encoding was correct,
* be unformatted but valid.
*/
@Override
public void transformLocal(ContentReader reader, ContentWriter writer, TransformationOptions options)
throws Exception
{
// is this a straight text-text transformation
transformText(reader, writer, options);
}
/**
* Transformation optimized for text-to-text conversion
*/
private void transformText(ContentReader reader, ContentWriter writer, TransformationOptions options) throws Exception
{
// get a char reader and writer
Reader charReader = null;
Writer charWriter = null;
try
{
if (reader.getEncoding() == null)
{
charReader = new InputStreamReader(reader.getContentInputStream());
}
else
{
charReader = new InputStreamReader(reader.getContentInputStream(), reader.getEncoding());
}
if (writer.getEncoding() == null)
{
charWriter = new OutputStreamWriter(writer.getContentOutputStream());
}
else
{
charWriter = new OutputStreamWriter(writer.getContentOutputStream(), writer.getEncoding());
}
// copy from the one to the other
char[] buffer = new char[8192];
int readCount = 0;
while (readCount > -1)
{
// write the last read count number of bytes
charWriter.write(buffer, 0, readCount);
// fill the buffer again
readCount = charReader.read(buffer);
}
}
finally
{
if (charReader != null)
{
try { charReader.close(); } catch (Throwable e) { logger.error(e); }
}
if (charWriter != null)
{
try { charWriter.close(); } catch (Throwable e) { logger.error(e); }
}
}
// done
}
@Override
protected void transformRemote(RemoteTransformerClient remoteTransformerClient, ContentReader reader,
ContentWriter writer, TransformationOptions options, String sourceMimetype,
String targetMimetype, String sourceExtension, String targetExtension,
String targetEncoding) throws Exception
{
String sourceEncoding = reader.getEncoding();
long timeoutMs = options.getTimeoutMs();
remoteTransformerClient.request(reader, writer, sourceMimetype, sourceExtension, targetExtension,
timeoutMs, logger,
"transformName", "string",
"sourceMimetype", sourceMimetype,
"targetMimetype", targetMimetype,
"targetExtension", targetExtension,
SOURCE_ENCODING, sourceEncoding,
TARGET_ENCODING, targetEncoding);
}
}

View File

@@ -1,69 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
/**
* Represents a supported transformation. Normally used in a spring bean that limits
* the number of supported configures.
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public class SupportedTransformation
{
private String sourceMimetype;
private String targetMimetype;
public SupportedTransformation()
{
}
public SupportedTransformation(String sourceMimetype, String targetMimetype)
{
this.sourceMimetype = sourceMimetype;
this.targetMimetype = targetMimetype;
}
public void setSourceMimetype(String sourceMimetype)
{
this.sourceMimetype = sourceMimetype;
}
public String getSourceMimetype()
{
return sourceMimetype;
}
public void setTargetMimetype(String targetMimetype)
{
this.targetMimetype = targetMimetype;
}
public String getTargetMimetype()
{
return targetMimetype;
}
}

View File

@@ -1,55 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import org.alfresco.repo.content.MimetypeMap;
import org.apache.tika.parser.Parser;
import org.apache.tika.parser.microsoft.OfficeParser;
/**
* This badly named transformer turns Microsoft Word documents
* (Word 6, 95, 97, 2000, 2003) into plain text, using Apache Tika.
*
* @author Nick Burch
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public class TextMiningContentTransformer extends TikaPoweredContentTransformer
{
public TextMiningContentTransformer()
{
super(new String[] {
MimetypeMap.MIMETYPE_WORD
});
setTransformerName("TextMining");
}
@Override
protected Parser getParser() {
return new OfficeParser();
}
}

View File

@@ -1,375 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.TransformationOptionLimits;
import org.alfresco.service.cmr.repository.TransformationOptionPair;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.tools.TextToPDF;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import static org.alfresco.repo.rendition2.RenditionDefinition2.SOURCE_ENCODING;
/**
* Makes use of the <a href="http://www.pdfbox.org/">PDFBox</a> library's <code>TextToPDF</code> utility.
*
* @author Derek Hulley
* @since 2.1.0
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public class TextToPdfContentTransformer extends AbstractRemoteContentTransformer
{
private static final Log logger = LogFactory.getLog(TextToPdfContentTransformer.class);
private PagedTextToPDF transformer;
public TextToPdfContentTransformer()
{
setPageLimitsSupported(true);
transformer = new PagedTextToPDF();
}
public void setStandardFont(String fontName)
{
try
{
transformer.setFont(transformer.getStandardFont(fontName));
}
catch (Throwable e)
{
throw new AlfrescoRuntimeException("Unable to set Standard Font for PDF generation: " + fontName, e);
}
}
public void setFontSize(int fontSize)
{
try
{
transformer.setFontSize(fontSize);
}
catch (Throwable e)
{
throw new AlfrescoRuntimeException("Unable to set Font Size for PDF generation: " + fontSize);
}
}
/**
* Only supports Text to PDF
*/
@Override
public boolean isTransformableMimetype(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
if ( (!MimetypeMap.MIMETYPE_TEXT_PLAIN.equals(sourceMimetype) &&
!MimetypeMap.MIMETYPE_TEXT_CSV.equals(sourceMimetype) &&
!MimetypeMap.MIMETYPE_DITA.equals(sourceMimetype) &&
!MimetypeMap.MIMETYPE_XML.equals(sourceMimetype) ) ||
!MimetypeMap.MIMETYPE_PDF.equals(targetMimetype))
{
// only support (text/plain OR text/csv OR text/xml) to (application/pdf)
return false;
}
else
{
return true;
}
}
@Override
public String getComments(boolean available)
{
return getCommentsOnlySupports(
Arrays.asList(new String[] {MimetypeMap.MIMETYPE_TEXT_PLAIN, MimetypeMap.MIMETYPE_TEXT_CSV,
MimetypeMap.MIMETYPE_DITA, MimetypeMap.MIMETYPE_XML}),
Arrays.asList(new String[] {MimetypeMap.MIMETYPE_PDF}), available);
}
@Override
protected Log getLogger()
{
return logger;
}
@Override
protected void transformLocal(
ContentReader reader,
ContentWriter writer,
TransformationOptions options) throws Exception
{
PDDocument pdf = null;
InputStream is = null;
InputStreamReader ir = null;
OutputStream os = null;
try
{
is = reader.getContentInputStream();
ir = buildReader(is, reader.getEncoding(), reader.getContentUrl());
TransformationOptionLimits limits = getLimits(reader, writer, options);
TransformationOptionPair pageLimits = limits.getPagesPair();
pdf = transformer.createPDFFromText(ir, pageLimits, reader.getContentUrl(), transformerDebug);
// dump it all to the writer
os = writer.getContentOutputStream();
pdf.save(os);
}
finally
{
if (pdf != null)
{
try { pdf.close(); } catch (Throwable e) {e.printStackTrace(); }
}
if (ir != null)
{
try { ir.close(); } catch (Throwable e) {e.printStackTrace(); }
}
if (is != null)
{
try { is.close(); } catch (Throwable e) {e.printStackTrace(); }
}
if (os != null)
{
try { os.close(); } catch (Throwable e) {e.printStackTrace(); }
}
}
}
@Override
protected void transformRemote(RemoteTransformerClient remoteTransformerClient, ContentReader reader,
ContentWriter writer, TransformationOptions options, String sourceMimetype,
String targetMimetype, String sourceExtension, String targetExtension,
String targetEncoding) throws Exception
{
String sourceEncoding = reader.getEncoding();
long timeoutMs = options.getTimeoutMs();
TransformationOptionLimits limits = getLimits(reader, writer, options);
TransformationOptionPair pageLimits = limits.getPagesPair();
int pageLimit = (int)pageLimits.getValue();
remoteTransformerClient.request(reader, writer, sourceMimetype, sourceExtension, targetExtension,
timeoutMs, logger,
"transformName", "textToPdf",
"sourceMimetype", sourceMimetype,
"targetMimetype", targetMimetype,
"targetExtension", targetExtension,
SOURCE_ENCODING, sourceEncoding,
"pageLimit", String.valueOf(pageLimit));
}
protected InputStreamReader buildReader(InputStream is, String encoding, String node)
{
// If they gave an encoding, try to use it
if(encoding != null)
{
Charset charset = null;
try
{
charset = Charset.forName(encoding);
} catch(Exception e)
{
logger.warn("JVM doesn't understand encoding '" + encoding +
"' when transforming " + node);
}
if(charset != null)
{
logger.debug("Processing plain text in encoding " + charset.displayName());
return new InputStreamReader(is, charset);
}
}
// Fall back on the system default
logger.debug("Processing plain text using system default encoding");
return new InputStreamReader(is);
}
private static class PagedTextToPDF extends TextToPDF
{
// REPO-1066: duplicating the following lines from org.apache.pdfbox.tools.TextToPDF because they made them private
// before the upgrade to pdfbox 2.0.8, in pdfbox 1.8, this piece of code was public in org.apache.pdfbox.pdmodel.font.PDType1Font
static PDType1Font getStandardFont(String name) {
return (PDType1Font)STANDARD_14.get(name);
}
private static final Map<String, PDType1Font> STANDARD_14 = new HashMap<String, PDType1Font>();
static
{
STANDARD_14.put(PDType1Font.TIMES_ROMAN.getBaseFont(), PDType1Font.TIMES_ROMAN);
STANDARD_14.put(PDType1Font.TIMES_BOLD.getBaseFont(), PDType1Font.TIMES_BOLD);
STANDARD_14.put(PDType1Font.TIMES_ITALIC.getBaseFont(), PDType1Font.TIMES_ITALIC);
STANDARD_14.put(PDType1Font.TIMES_BOLD_ITALIC.getBaseFont(), PDType1Font.TIMES_BOLD_ITALIC);
STANDARD_14.put(PDType1Font.HELVETICA.getBaseFont(), PDType1Font.HELVETICA);
STANDARD_14.put(PDType1Font.HELVETICA_BOLD.getBaseFont(), PDType1Font.HELVETICA_BOLD);
STANDARD_14.put(PDType1Font.HELVETICA_OBLIQUE.getBaseFont(), PDType1Font.HELVETICA_OBLIQUE);
STANDARD_14.put(PDType1Font.HELVETICA_BOLD_OBLIQUE.getBaseFont(), PDType1Font.HELVETICA_BOLD_OBLIQUE);
STANDARD_14.put(PDType1Font.COURIER.getBaseFont(), PDType1Font.COURIER);
STANDARD_14.put(PDType1Font.COURIER_BOLD.getBaseFont(), PDType1Font.COURIER_BOLD);
STANDARD_14.put(PDType1Font.COURIER_OBLIQUE.getBaseFont(), PDType1Font.COURIER_OBLIQUE);
STANDARD_14.put(PDType1Font.COURIER_BOLD_OBLIQUE.getBaseFont(), PDType1Font.COURIER_BOLD_OBLIQUE);
STANDARD_14.put(PDType1Font.SYMBOL.getBaseFont(), PDType1Font.SYMBOL);
STANDARD_14.put(PDType1Font.ZAPF_DINGBATS.getBaseFont(), PDType1Font.ZAPF_DINGBATS);
}
//duplicating until here
// The following code is based on the code in TextToPDF with the addition of
// checks for page limits.
// The calling code must close the PDDocument once finished with it.
public PDDocument createPDFFromText(Reader text, TransformationOptionPair pageLimits, String contentUrl, TransformerDebug transformerDebug)
throws IOException
{
int pageLimit = (int)pageLimits.getValue();
PDDocument doc = null;
int pageCount = 0;
try
{
final int margin = 40;
float height = getFont().getFontDescriptor().getFontBoundingBox().getHeight()/1000;
//calculate font height and increase by 5 percent.
height = height*getFontSize()*1.05f;
doc = new PDDocument();
BufferedReader data = new BufferedReader( text );
String nextLine = null;
PDPage page = new PDPage();
PDPageContentStream contentStream = null;
float y = -1;
float maxStringLength = page.getMediaBox().getWidth() - 2*margin;
// There is a special case of creating a PDF document from an empty string.
boolean textIsEmpty = true;
outer:
while( (nextLine = data.readLine()) != null )
{
// The input text is nonEmpty. New pages will be created and added
// to the PDF document as they are needed, depending on the length of
// the text.
textIsEmpty = false;
String[] lineWords = nextLine.trim().split( " " );
int lineIndex = 0;
while( lineIndex < lineWords.length )
{
StringBuffer nextLineToDraw = new StringBuffer();
float lengthIfUsingNextWord = 0;
do
{
nextLineToDraw.append( lineWords[lineIndex] );
nextLineToDraw.append( " " );
lineIndex++;
if( lineIndex < lineWords.length )
{
String lineWithNextWord = nextLineToDraw.toString() + lineWords[lineIndex];
lengthIfUsingNextWord =
(getFont().getStringWidth( lineWithNextWord )/1000) * getFontSize();
}
}
while( lineIndex < lineWords.length &&
lengthIfUsingNextWord < maxStringLength );
if( y < margin )
{
if (pageLimit > 0 && pageCount++ >= pageLimit)
{
pageLimits.getAction().throwIOExceptionIfRequired("Page limit ("+pageLimit+
") reached.", transformerDebug);
break outer;
}
// We have crossed the end-of-page boundary and need to extend the
// document by another page.
page = new PDPage();
doc.addPage( page );
if( contentStream != null )
{
contentStream.endText();
contentStream.close();
}
contentStream = new PDPageContentStream(doc, page);
contentStream.setFont(getFont(), getFontSize());
contentStream.beginText();
y = page.getMediaBox().getHeight() - margin + height;
contentStream.moveTextPositionByAmount(
margin, y );
}
//System.out.println( "Drawing string at " + x + "," + y );
if( contentStream == null )
{
throw new IOException( "Error:Expected non-null content stream." );
}
contentStream.moveTextPositionByAmount( 0, -height);
y -= height;
contentStream.drawString( nextLineToDraw.toString() );
}
}
// If the input text was the empty string, then the above while loop will have short-circuited
// and we will not have added any PDPages to the document.
// So in order to make the resultant PDF document readable by Adobe Reader etc, we'll add an empty page.
if (textIsEmpty)
{
doc.addPage(page);
}
if( contentStream != null )
{
contentStream.endText();
contentStream.close();
}
}
catch( IOException io )
{
if( doc != null )
{
doc.close();
}
throw io;
}
return doc;
}
}
}

View File

@@ -1,135 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import java.util.ArrayList;
import org.apache.tika.config.TikaConfig;
import org.apache.tika.mime.MediaType;
import org.apache.tika.parser.AutoDetectParser;
import org.apache.tika.parser.Parser;
/**
* A Content Extractor for XML, HTML and Text,
* which makes use of the Apache Tika
* auto-detection to select the best parser
* to process your document.
* This will be used for all files which Tika can
* handle, but where no other more explicit
* extractor is defined.
*
* @author Nick Burch
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public class TikaAutoContentTransformer extends TikaPoweredContentTransformer
{
private static AutoDetectParser parser;
private static TikaConfig config;
/**
* We support all the mimetypes that the Tika
* auto-detect parser can handle, except for
* Image, Audio and Video ones which don't
* make much sense
*/
public static ArrayList<String> SUPPORTED_MIMETYPES;
private static ArrayList<String> buildMimeTypes(TikaConfig tikaConfig)
{
config = tikaConfig;
parser = new AutoDetectParser(config);
SUPPORTED_MIMETYPES = new ArrayList<String>();
for(MediaType baseType : parser.getParsers().keySet())
{
// Register both the canonical type, and any alias it may have
// Alfresco sometimes uses the canonical type, and sometimes an alias
ArrayList<MediaType> types = new ArrayList<MediaType>();
types.add(baseType);
types.addAll( config.getMediaTypeRegistry().getAliases(baseType) );
for(MediaType mt : types)
{
if(mt.toString().startsWith("application/vnd.oasis.opendocument.formula")) {
// TODO Tika support for quick.odf, mimetype=application/vnd.oasis.opendocument.formula
// TODO Tika support for quick.otf, mimetype=application/vnd.oasis.opendocument.formula-template
continue;
}
if(mt.toString().startsWith("application/vnd.oasis.opendocument.graphics")) {
// TODO Tika support for quick.odg, mimetype=application/vnd.oasis.opendocument.graphics
// TODO Tika support for quick.otg, mimetype=application/vnd.oasis.opendocument.graphics-template
continue;
}
if(mt.getType().equals("image") ||
mt.getType().equals("audio") ||
mt.getType().equals("video"))
{
// Skip these, as Tika mostly just does
// metadata rather than content
}
else if(mt.toString().equals("application/zip") ||
mt.toString().equals("application/tar") ||
mt.toString().equals("application/x-tar"))
{
// Skip these, as we handle container formats in a different
// transformer to give the user control over recursion
}
else if(mt.toString().equals("message/rfc822") ||
mt.toString().equals("application/vnd.ms-outlook"))
{
// Skip these, as we want our textual representations to include
// parts of the metadata (eg people, subjects, dates) too
}
else
{
// Tika can probably do some useful text
SUPPORTED_MIMETYPES.add( mt.toString() );
}
}
}
return SUPPORTED_MIMETYPES;
}
public TikaAutoContentTransformer(TikaConfig tikaConfig)
{
super( buildMimeTypes(tikaConfig) );
setUseTimeoutThread(true);
setTransformerName("TikaAuto");
}
/**
* Returns the Tika Auto-Detection
* parser, which will try to
* process all documents that Tika
* knows about
*/
protected Parser getParser()
{
return parser;
}
}

View File

@@ -1,343 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.action.ParameterDefinitionImpl;
import org.alfresco.repo.action.executer.ActionExecuterAbstractBase;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.ParameterDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tika.config.TikaConfig;
import org.apache.tika.detect.DefaultDetector;
import org.apache.tika.detect.Detector;
import org.apache.tika.exception.TikaException;
import org.apache.tika.extractor.EmbeddedResourceHandler;
import org.apache.tika.extractor.ParserContainerExtractor;
import org.apache.tika.io.TikaInputStream;
import org.apache.tika.mime.MediaType;
import org.apache.tika.parser.AutoDetectParser;
/**
* Warning - this is a prototype service, and will likely change dramatically
* in Alfresco 4.0!
*
* This proto-service provides a way to have Apache Tika extract out
* certain kinds of embedded resources from within a container file.
*
* One use might be to extract all the images in a zip file, another might
* be to fetch all the Word Documents embedded in an Excel Spreadsheet.
*
* Uses the Apache Tika ContainerExtractor framework, along with the
* Apache Tika Auto-Parser.
*
* Not sprung-in by default, you will need to manually list this in
* an extension context file.
*
* @author Nick Burch
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public class TikaPoweredContainerExtractor
{
private static final Log logger = LogFactory.getLog(TikaPoweredContainerExtractor.class);
private NodeService nodeService;
private ContentService contentService;
private TikaConfig config;
private AutoDetectParser parser;
private Detector detector;
/**
* Injects the nodeService bean.
*
* @param nodeService the nodeService.
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* Injects the contentService bean.
*
* @param contentService the contentService.
*/
public void setContentService(ContentService contentService)
{
this.contentService = contentService;
}
/**
* Injects the TikaConfig to use
*
* @param tikaConfig The Tika Config to use
*/
public void setTikaConfig(TikaConfig tikaConfig)
{
this.config = tikaConfig;
// Setup the detector and parser
detector = new DefaultDetector(config.getMimeRepository());
parser = new AutoDetectParser(detector);
}
/**
* Extracts out all the entries from the container
* that match the supplied list of mime types.
* If no mime types are specified, extracts all
* available embedded resources.
*/
public List<NodeRef> extract(NodeRef source, List<String> mimetypes)
{
// Grab the directory to put the nodes into
// Will be the parent folder of the source
NodeRef folder = nodeService.getPrimaryParent(source).getParentRef();
// Get the contents
ContentReader reader = contentService.getReader(source, ContentModel.PROP_CONTENT);
InputStream wrappedInputStream = null;
TikaInputStream stream = null;
Extractor handler = null;
try {
wrappedInputStream = reader.getContentInputStream();
stream = TikaInputStream.get(wrappedInputStream);
// Build the recursing parser
handler = new Extractor(folder, mimetypes);
// Have Tika look for things
ParserContainerExtractor extractor = new ParserContainerExtractor(
parser, detector
);
logger.info("Beginning extraction of " + source.toString());
extractor.extract(stream, null, handler);
logger.info("Completed extraction of " + source.toString());
} catch(TikaException te) {
throw new AlfrescoRuntimeException("Extraction Failed", te);
} catch(IOException ie) {
throw new AlfrescoRuntimeException("Extraction Failed", ie);
}
finally
{
// Tidy up
if (stream != null)
{
try
{
stream.close();
}
catch (IOException error)
{
logger.debug("Error while closing stream.", error);
}
}
if (wrappedInputStream != null)
{
try
{
wrappedInputStream.close();
}
catch (IOException error)
{
logger.debug("Error while closing stream.", error);
}
}
}
// All done
return handler.extracted;
}
/**
* This EmbeddedResourceHandler is called by Tika for each
* embedded resource. It decides if the resource is to
* be extracted or not, and if it is, saves it into the
* specified folder.
*/
private class Extractor implements EmbeddedResourceHandler
{
private List<NodeRef> extracted;
private Set<MediaType> acceptTypes;
private NodeRef folder;
private int anonymousCount = 0;
private Extractor(NodeRef folder, List<String> types)
{
this.folder = folder;
this.extracted = new ArrayList<NodeRef>();
if(types != null && types.size() > 0)
{
acceptTypes = new HashSet<MediaType>();
for(String type : types)
{
acceptTypes.add(MediaType.parse(type));
}
}
}
@Override
public void handle(String filename, MediaType mediaType,
InputStream stream) {
// Do we want it?
if(acceptTypes == null || acceptTypes.contains(mediaType))
{
// Ensure we have a filename
if(filename == null)
{
anonymousCount++;
filename = "embedded"+anonymousCount+"."+mediaType.getSubtype();
}
logger.info("Extracting embedded " + mediaType + " entry " + filename);
// Save it
Map<QName,Serializable> properties = new HashMap<QName,Serializable>();
properties.put(ContentModel.PROP_NAME, filename);
NodeRef node = nodeService.createNode(
folder,
ContentModel.ASSOC_CONTAINS,
QName.createQName(filename),
ContentModel.TYPE_CONTENT,
properties
).getChildRef();
ContentWriter writer = contentService.getWriter(
node, ContentModel.PROP_CONTENT, true
);
writer.setMimetype(mediaType.toString());
writer.putContent(stream);
}
else
{
logger.info("Skipping embedded " + mediaType + " entry " + filename);
}
}
}
/**
* This action executor allows you to trigger extraction as an
* action, perhaps from a rule.
*
* Not sprung-in by default, you will need to manually list this in
* an extension context file. You will also need to add properties
* files entries.
*/
public static class ExtractorActionExecutor extends ActionExecuterAbstractBase
{
public static final String NAME = "extractEmbeddedResources";
public static final String PARAM_MIME_TYPES = "mime-types";
private TikaPoweredContainerExtractor extractor;
public void setTikaPoweredContainerExtractor(TikaPoweredContainerExtractor extractor)
{
this.extractor = extractor;
}
@Override
protected void addParameterDefinitions(List<ParameterDefinition> paramList) {
paramList.add(new ParameterDefinitionImpl(
PARAM_MIME_TYPES,
DataTypeDefinition.TEXT,
false,
getParamDisplayLabel(PARAM_MIME_TYPES)
));
}
@Override
protected void executeImpl(Action action, NodeRef actionedUponNodeRef) {
List<String> mimeTypes = null;
String rawTypes = (String)action.getParameterValue(PARAM_MIME_TYPES);
if(rawTypes != null && rawTypes.length() > 0)
{
mimeTypes = new ArrayList<String>();
StringTokenizer st = new StringTokenizer(rawTypes, ",");
while(st.hasMoreTokens())
{
mimeTypes.add( st.nextToken().trim() );
}
}
extractor.extract(actionedUponNodeRef, mimeTypes);
}
}
/*
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<beans>
<bean id="tikaPoweredContainerExtractor" class="org.alfresco.repo.content.transform.TikaPoweredContainerExtractor">
<property name="nodeService">
<ref bean="NodeService" />
</property>
<property name="contentService">
<ref bean="ContentService" />
</property>
<property name="tikaConfig">
<bean class="org.apache.tika.config.TikaConfig" factory-method="getDefaultConfig" />
</property>
</bean>
<bean id="extractEmbeddedResources" class="org.alfresco.repo.content.transform.TikaPoweredContainerExtractor$ExtractorActionExecutor" parent="action-executer">
<property name="tikaPoweredContainerExtractor">
<ref bean="tikaPoweredContainerExtractor" />
</property>
</bean>
<bean id="extractEmbeddedResources-action-messages" class="org.alfresco.i18n.ResourceBundleBootstrapComponent">
<property name="resourceBundles">
<list>
<value>alfresco.extension.extractor-action-messages</value>
</list>
</property>
</bean>
</beans>
*/
/*
extractEmbeddedResources.title=Extract embedded resources
extractEmbeddedResources.description=Extract resources from within container files, such as .zip or .docx
extractEmbeddedResources.param_mime-types.display-label=Mime Types
*/
}

View File

@@ -1,323 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Arrays;
import java.util.List;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tika.extractor.DocumentSelector;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.Parser;
import org.apache.tika.sax.BodyContentHandler;
import org.apache.tika.sax.ExpandedTitleContentHandler;
import org.xml.sax.ContentHandler;
import static org.alfresco.repo.rendition2.RenditionDefinition2.TARGET_ENCODING;
/**
* Provides helpful services for {@link org.alfresco.repo.content.transform.ContentTransformer}
* implementations which are powered by Apache Tika.
*
* To use Tika to transform some content into Text, Html or XML, create an
* implementation of this / use the Auto Detect transformer.
*
* For now, all transformers are registered as regular, rather than explicit
* transformations. This should allow you to register your own explicit
* transformers and have them nicely take priority.
*
* @author Nick Burch
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public abstract class TikaPoweredContentTransformer extends AbstractRemoteContentTransformer
{
private static final Log logger = LogFactory.getLog(TikaPoweredContentTransformer.class);
private static final List<String> TARGET_MIMETYPES = Arrays.asList(new String[] {
MimetypeMap.MIMETYPE_TEXT_PLAIN,
MimetypeMap.MIMETYPE_HTML,
MimetypeMap.MIMETYPE_XHTML,
MimetypeMap.MIMETYPE_XML});
private static final double MEGABYTES = 1024.0 * 1024.0;
private static final String USAGE_PATTERN = "Content transformation has completed:\n" +
" Transformer: %s\n" +
" Content Reader: %s\n" +
" Memory (MB): Used/Total/Maximum - %f/%f/%f\n" +
" Time Spent: %d ms";
protected List<String> sourceMimeTypes;
private String transformerName;
protected DocumentSelector documentSelector;
/**
* Windows carriage return line feed pair.
*/
protected static final String LINE_BREAK = "\r\n";
public static final String WRONG_FORMAT_MESSAGE_ID = "transform.err.format_or_password";
protected TikaPoweredContentTransformer(List<String> sourceMimeTypes)
{
this.sourceMimeTypes = sourceMimeTypes;
}
protected TikaPoweredContentTransformer(String[] sourceMimeTypes)
{
this(Arrays.asList(sourceMimeTypes));
}
public void setTransformerName(String transformerName)
{
this.transformerName = transformerName;
}
@Override
protected Log getLogger()
{
return logger;
}
/**
* Returns the correct Tika Parser to process
* the document.
* If you don't know which you want, use
* {@link TikaAutoContentTransformer} which
* makes use of the Tika auto-detection.
*/
protected abstract Parser getParser();
/**
* Can we do the requested transformation via Tika?
* We support transforming to HTML, XML or Text
*/
@Override
public boolean isTransformableMimetype(String sourceMimetype, String targetMimetype, TransformationOptions options)
{
if(! sourceMimeTypes.contains(sourceMimetype))
{
// The source isn't one of ours
return false;
}
if (TARGET_MIMETYPES.contains(targetMimetype))
{
// We can output to this
return true;
}
else
{
// We support the source, but not the target
return false;
}
}
@Override
public String getComments(boolean available)
{
return getCommentsOnlySupports(sourceMimeTypes, TARGET_MIMETYPES, available);
}
/**
* Returns an appropriate Tika ContentHandler for the
* requested content type. Normally you'll let this
* work as default, but if you need fine-grained
* control of how the Tika events become text then
* override and supply your own.
*/
protected ContentHandler getContentHandler(String targetMimeType, Writer output)
throws TransformerConfigurationException
{
if(MimetypeMap.MIMETYPE_TEXT_PLAIN.equals(targetMimeType))
{
return new BodyContentHandler(output);
}
SAXTransformerFactory factory = (SAXTransformerFactory)
SAXTransformerFactory.newInstance();
TransformerHandler handler = factory.newTransformerHandler();
handler.getTransformer().setOutputProperty(OutputKeys.INDENT, "yes");
handler.setResult(new StreamResult(output));
if(MimetypeMap.MIMETYPE_HTML.equals(targetMimeType))
{
handler.getTransformer().setOutputProperty(OutputKeys.METHOD, "html");
return new ExpandedTitleContentHandler(handler);
}
else if(MimetypeMap.MIMETYPE_XHTML.equals(targetMimeType) ||
MimetypeMap.MIMETYPE_XML.equals(targetMimeType))
{
handler.getTransformer().setOutputProperty(OutputKeys.METHOD, "xml");
}
else
{
throw new TransformerInfoException(
WRONG_FORMAT_MESSAGE_ID,
new IllegalArgumentException("Requested target type " + targetMimeType + " not supported")
);
}
return handler;
}
/**
* Sets the document selector, used for determining whether to parse embedded resources.
*
* @param documentSelector DocumentSelector
*/
public void setDocumentSelector(DocumentSelector documentSelector)
{
this.documentSelector = documentSelector;
}
/**
* Gets the document selector, used for determining whether to parse embedded resources,
* null by default so parse all.
*
* @param metadata Metadata
* @param targetMimeType String
* @param options TransformationOptions
* @return the document selector
*/
protected DocumentSelector getDocumentSelector(Metadata metadata, String targetMimeType, TransformationOptions options)
{
return documentSelector;
}
/**
* By default returns a ParseContent that does not recurse
*/
protected ParseContext buildParseContext(Metadata metadata, String targetMimeType, TransformationOptions options)
{
ParseContext context = new ParseContext();
DocumentSelector selector = getDocumentSelector(metadata, targetMimeType, options);
if (selector != null)
{
context.set(DocumentSelector.class, selector);
}
return context;
}
@Override
public void transformLocal(ContentReader reader, ContentWriter writer, TransformationOptions options)
throws Exception
{
OutputStream os = writer.getContentOutputStream();
String encoding = writer.getEncoding();
String targetMimeType = writer.getMimetype();
Writer ow = new OutputStreamWriter(os, encoding);
Parser parser = getParser();
Metadata metadata = new Metadata();
ParseContext context = buildParseContext(metadata, targetMimeType, options);
ContentHandler handler = getContentHandler(targetMimeType, ow);
if(handler == null)
{
throw new TransformerConfigurationException(
"Unable to create Tika Handler for configured output " + targetMimeType
);
}
InputStream is = null;
long startTime = 0;
try {
is = reader.getContentInputStream();
if (logger.isDebugEnabled())
{
startTime = System.currentTimeMillis();
}
parser.parse(is, handler, metadata, context);
}
finally
{
if(logger.isDebugEnabled())
{
logger.debug(calculateMemoryAndTimeUsage(reader, startTime));
}
if (is != null)
{
try { is.close(); } catch (Throwable e) {}
}
if (ow != null)
{
try { ow.close(); } catch (Throwable e) {}
}
if (os != null)
{
try { os.close(); } catch (Throwable e) {}
}
}
}
@Override
protected void transformRemote(RemoteTransformerClient remoteTransformerClient, ContentReader reader,
ContentWriter writer, TransformationOptions options,
String sourceMimetype, String targetMimetype,
String sourceExtension, String targetExtension,
String targetEncoding) throws Exception
{
long timeoutMs = options.getTimeoutMs();
remoteTransformerClient.request(reader, writer, sourceMimetype, sourceExtension, targetExtension,
timeoutMs, logger,
"transformName", transformerName,
"sourceMimetype", sourceMimetype,
"targetMimetype", targetMimetype,
"targetExtension", targetExtension,
TARGET_ENCODING, targetEncoding);
}
private String calculateMemoryAndTimeUsage(ContentReader reader, long startTime)
{
long endTime = System.currentTimeMillis();
Runtime runtime = Runtime.getRuntime();
long totalMemory = runtime.totalMemory();
return String.format(USAGE_PATTERN, this.getClass().getName(), reader, (totalMemory - runtime.freeMemory()) / MEGABYTES, totalMemory / MEGABYTES, runtime.maxMemory()
/ MEGABYTES, (endTime - startTime));
}
}

View File

@@ -1,392 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.alfresco.api.AlfrescoPublicApi;
import org.alfresco.service.cmr.repository.NodeRef;
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
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
@AlfrescoPublicApi
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";
/**
* An optional separator appended after the normal suffix and following value that
* identifies the 'use' or 'application' of the property. Example uses include 'index'
* 'doclib' and 'preview'. The corresponding configuration value is only used in the
* context of the specified usage.
*/
static final String USE = ".use.";
/**
* The separator between the transformer name and two mimetype extensions in a property name.
*/
static final String EXTENSIONS = ".extensions.";
/**
* The separator between the transformer name and wildcarded mimetypes rather than extensions in a property name.
* Effectively equivalent to multiple properties using the {@link #EXTENSIONS}.
*/
static final String MIMETYPES = ".mimetypes.";
/**
* Both extension and minetype separators.
*/
public static String[] SEPARATORS = new String[] {EXTENSIONS , MIMETYPES};
/**
* The suffix to property names for creating dynamic complex transformers
*/
public static final String PIPELINE = ".pipeline";
/**
* The suffix to property names for creating dynamic failover transformers
*/
public static final String FAILOVER = ".failover";
/**
* The suffix to property names to indicate that a transformer is available.
* If not specified, defaults to true, indicating it may be selected rather
* only being available as a component of another transformer.
*/
public static final String AVAILABLE = ".available";
/**
* Separator between transformers and mimetype extensions in a dynamic compound property value.
*/
public static final char PIPE = '|';
/**
* 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 blacklist.
*/
static final String BLACKLIST = ".blacklist";
/**
* The suffix to property names to indicate which Alfresco version the transformer is
* available with. If not specified it is not restricted. So if set to "Enterprise" it
* is not available to Community.
* @see #AMP
*/
static final String EDITION = ".edition";
/**
* The suffix to property names to indicate which Alfresco AMPs the transformer is
* available with. The value should be the AMP's ID. If not specified it is not restricted.
* @see #EDITION
*/
static final String AMP = ".amp";
/**
* 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";
/**
* Suffixes for limits.
*/
static final String MAX_SOURCE_SIZE_K_BYTES = '.'+TransformationOptionLimits.OPT_MAX_SOURCE_SIZE_K_BYTES;
static final String TIMEOUT_MS = '.'+TransformationOptionLimits.OPT_TIMEOUT_MS;
static final String MAX_PAGES = '.'+TransformationOptionLimits.OPT_MAX_PAGES;
static final String READ_LIMIT_K_BYTES = '.'+TransformationOptionLimits.OPT_READ_LIMIT_K_BYTES;
static final String READ_LIMIT_TIME_MS = '.'+TransformationOptionLimits.OPT_READ_LIMIT_TIME_MS;
static final String PAGE_LIMIT = '.'+TransformationOptionLimits.OPT_PAGE_LIMIT;
/**
* To support the historical concept of EXPLICIT transformers, all such transformers
* are given a {@link #PRIORITY_EXPLICIT} (50). By default transformers have a default of 10.
* A value of 5 allows better transformers to be added later.
*/
public int PRIORITY_EXPLICIT = 50;
/**
* By default transformers have a priority of 100.
*/
public int PRIORITY_DEFAULT = 100;
/**
* Suffixes to property names used to define transformation limits
*/
static final Collection<String> LIMIT_SUFFIXES = Arrays.asList(new String [] {
MAX_SOURCE_SIZE_K_BYTES,
TIMEOUT_MS,
MAX_PAGES,
READ_LIMIT_K_BYTES,
READ_LIMIT_TIME_MS,
PAGE_LIMIT
});
/**
* Suffix pairs (max and limit values) to property names used to define transformation limits
*/
public final String[][] LIMIT_PAIR_SUFFIXES = new String[][]
{
{MAX_SOURCE_SIZE_K_BYTES, READ_LIMIT_K_BYTES},
{TIMEOUT_MS, READ_LIMIT_TIME_MS},
{MAX_PAGES, PAGE_LIMIT}
};
/**
* All suffixes to property names used to transformer configuration
*/
static final Collection<String> ALL_SUFFIXES = Arrays.asList(new String [] {
MAX_SOURCE_SIZE_K_BYTES,
TIMEOUT_MS,
MAX_PAGES,
READ_LIMIT_K_BYTES,
READ_LIMIT_TIME_MS,
PAGE_LIMIT,
SUPPORTED,
AVAILABLE,
PRIORITY,
BLACKLIST,
ERROR_TIME,
INITIAL_TIME,
INITIAL_COUNT,
THRESHOLD_COUNT,
FAILOVER,
PIPELINE
});
/**
* No suffixes to property names used to define transformer settings.
*/
public static final Collection<String> NO_SUFFIXES = Collections.singletonList("");
static final String ENTRIES = "entries";
/**
* The number of debug lines to keep. Turned off if <= 0.
*/
public static final String DEBUG_ENTRIES = TRANSFORMER+"debug."+ENTRIES;
/**
* The number of log lines to keep. Turned off if <= 0.
*/
public static final String LOG_ENTRIES = TRANSFORMER+"log."+ENTRIES;
/**
* A white list of declared and detected mimetypes, that don't match, but should still be transformed.
*/
// Has ".mimetypes" on the end as we might one day wish to use extensions too (to simplify the entry).
static final String STRICT_MIMETYPE_CHECK_WHITELIST_MIMETYPES = TRANSFORMER+"strict.mimetype.check.whitelist"+MIMETYPES.substring(0, MIMETYPES.length()-1);
/**
* Returns a transformer property value.
* @param name of the property.
* @return a transformer property or {@code null} if not set.
*/
String getProperty(String name);
/**
* Returns a sorted set of all transformer properties, their values and includes
* comments about the properties.
* @param changesOnly only custom values will be included.
* @return a multi-line String which is never {code null}.
*/
String getProperties(boolean changesOnly);
/**
* Removes transformer properties.
*
* @param propertyNames new line separated names. Any values will be ignored.
* @return the number of properties removed.
* @throws IllegalArgumentException if the properties were not set or the
* list contains errors.
*/
int removeProperties(String propertyNames);
/**
* Sets a transformer property values. These will be stored in the database but on an MBean
* reset is cleared.
*
* @param propertyNamesAndValues new line separated name and values
* @return the number of properties set.
* @throws IllegalArgumentException the list contains errors.
*/
int setProperties(String propertyNamesAndValues);
/**
* 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.
* @param createNew indicates if a new object should be created if it does not exist.
* @return the requested {@link TransformerStatistics}.
*/
public TransformerStatistics getStatistics(ContentTransformer transformer, String sourceMimetype, String targetMimetype, boolean createNew);
/**
* 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
* @param use to which the limits will be put. For example "index", "webpreview", "doclib", "syncRule",
* "aysncRule". {@code null} is the default.
* @return the combined (takes into account defaults from higher levels) limits for the combination.
*/
public TransformationOptionLimits getLimits(ContentTransformer transformer, String sourceMimetype, String targetMimetype, String use);
/**
* 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 contentTransformerHelper
* @param sourceMimetype
* @param targetMimetype
* @return the priority. To support the historical concept of EXPLICIT transformers, all such transformers
* are given a {@link #PRIORITY_EXPLICIT} (50). By default transformers have a default of 100.
*/
public int getPriority(ContentTransformer contentTransformerHelper,
String sourceMimetype, String targetMimetype);
/**
* Returns a list of blacklisted NodeRefs of the specified transformer for the the combination of source and target mimetype.
* @param transformer
* @param sourceMimetype
* @param targetMimetype
* @return the blacklist or null is none.
*/
List<NodeRef> getBlacklist(ContentTransformer transformer, String sourceMimetype,
String targetMimetype);
/**
* When strict mimetype checking is performed before a transformation, this method is called.
* There are a few issues with the Tika mimetype detection. As a result we still allow some
* transformations to take place even if there is a discrepancy between the detected and
* declared mimetypes.
* @param declaredMimetype the mimetype on the source node
* @param detectedMimetype returned by Tika having looked at the content.
* @return true if the transformation should take place. This includes the case where the
* detectedMimetype is null (returned by Tika when the mimetypes are the same), or
* the supplied pair of mimetypes have been added to the
* {@code}transformer.strict.mimetype.check.whitelist{@code}.
*/
boolean strictMimetypeCheck(String declaredMimetype, String detectedMimetype);
/**
* Returns the threshold of the transformer. It is only after this number of transformation attempts
* that the average time is used.
* @param contentTransformerHelper
* @param sourceMimetype
* @param targetMimetype
* @return the threshold.
*/
public int getThresholdCount(ContentTransformer contentTransformerHelper, String sourceMimetype,
String targetMimetype);
}

View File

@@ -1,353 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import static org.alfresco.repo.content.transform.TransformerConfig.AMP;
import static org.alfresco.repo.content.transform.TransformerConfig.AVAILABLE;
import static org.alfresco.repo.content.transform.TransformerConfig.EDITION;
import static org.alfresco.repo.content.transform.TransformerConfig.FAILOVER;
import static org.alfresco.repo.content.transform.TransformerConfig.PIPE;
import static org.alfresco.repo.content.transform.TransformerConfig.PIPELINE;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.rendition2.LegacySynchronousTransformClient;
import org.alfresco.service.cmr.module.ModuleService;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.MimetypeService;
import org.alfresco.service.descriptor.DescriptorService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Adds dynamic transformers defined in alfresco global properties to the ContentTransformerRegistry.
*
* @author Alan Davis
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public class TransformerConfigDynamicTransformers extends TransformerPropertyNameExtractor
{
private static final Log logger = LogFactory.getLog(TransformerConfigDynamicTransformers.class);
int errorCount = 0;
private final List<ContentTransformer> dynamicTransformers = new ArrayList<ContentTransformer>();
public TransformerConfigDynamicTransformers(TransformerConfig transformerConfig, TransformerProperties transformerProperties,
MimetypeService mimetypeService, LegacySynchronousTransformClient legacySynchronousTransformClient, ContentTransformerRegistry transformerRegistry,
TransformerDebug transformerDebug, ModuleService moduleService, DescriptorService descriptorService,
Properties globalProperties)
{
createDynamicTransformers(transformerConfig, transformerProperties, mimetypeService, legacySynchronousTransformClient,
transformerRegistry, transformerDebug, moduleService, descriptorService, globalProperties);
}
private void createDynamicTransformers(TransformerConfig transformerConfig, TransformerProperties transformerProperties,
MimetypeService mimetypeService, LegacySynchronousTransformClient legacySynchronousTransformClient, ContentTransformerRegistry transformerRegistry,
TransformerDebug transformerDebug, ModuleService moduleService, DescriptorService descriptorService,
Properties globalProperties)
{
Collection<String> SUFFIXES = Arrays.asList(new String [] {
FAILOVER,
PIPELINE,
AVAILABLE,
EDITION,
AMP
});
Map<TransformerSourceTargetSuffixKey, TransformerSourceTargetSuffixValue>
transformerSourceTargetSuffixValues =
getTransformerSourceTargetValuesMap(SUFFIXES, true, true, false, transformerProperties, mimetypeService);
Collection<TransformerSourceTargetSuffixValue> properties =
transformerSourceTargetSuffixValues.values();
// Repeat until we cannot create any more transformers or all have been created
Collection<TransformerSourceTargetSuffixValue> processed =
new ArrayList<TransformerSourceTargetSuffixValue>();
do
{
processed.clear();
for (TransformerSourceTargetSuffixValue property: properties)
{
if (property.suffix.equals(PIPELINE) || property.suffix.equals(FAILOVER))
{
try
{
String edition = getProperty(property.transformerName, null, null, EDITION,
null, transformerSourceTargetSuffixValues);
String moduleId = getProperty(property.transformerName, null, null, AMP,
null, transformerSourceTargetSuffixValues);
if (!supportedEdition(descriptorService, edition))
{
processed.add(property);
logger.debug(property.transformerName+" ignored. As it is an "+edition+" only transformer.");
}
else if (!supportedModule(moduleService, moduleId))
{
processed.add(property);
logger.debug(property.transformerName+" ignored. As the AMP "+moduleId+" is not installed.");
}
else
{
String availableStr = getProperty(property.transformerName, null, null, AVAILABLE,
null, transformerSourceTargetSuffixValues);
boolean available = availableStr == null || "true".equalsIgnoreCase(availableStr);
AbstractContentTransformer2 transformer = property.suffix.equals(PIPELINE)
? createComplexTransformer(property, transformerConfig, mimetypeService,
legacySynchronousTransformClient, transformerRegistry, transformerDebug, available,
globalProperties)
: createFailoverTransformer(property, transformerConfig, mimetypeService,
transformerRegistry, transformerDebug, available,
globalProperties);
transformer.register();
processed.add(property);
dynamicTransformers.add(transformer);
logger.debug(property.transformerName+" added");
}
}
catch (IllegalArgumentException e)
{
// Thrown if unknown sub transformer name - it might be dynamic
}
catch (AlfrescoRuntimeException e)
{
// Thrown if the mimetype is invalid or the transformer already exists
processed.add(property);
error(e.getMessage());
}
}
}
} while (properties.removeAll(processed) && properties.size() > 0);
for (TransformerSourceTargetSuffixValue property: properties)
{
if (property.suffix.equals(PIPELINE) || property.suffix.equals(FAILOVER))
{
error("Cannot create dynamic transformer "+property.transformerName+
" as sub transformers could not be found or created (\""+
property.value+"\").");
}
}
}
private boolean supportedEdition(DescriptorService descriptorService, String edition)
{
return descriptorService == null || edition == null ||
descriptorService.getServerDescriptor().getEdition().equals(edition);
}
private boolean supportedModule(ModuleService moduleService, String moduleId)
{
return moduleService == null || moduleId == null ||
moduleService.getModule(moduleId) != null;
}
private AbstractContentTransformer2 createComplexTransformer(TransformerSourceTargetSuffixValue property,
TransformerConfig transformerConfig,
MimetypeService mimetypeService, LegacySynchronousTransformClient legacySynchronousTransformClient,
ContentTransformerRegistry transformerRegistry, TransformerDebug transformerDebug,
boolean available, Properties globalProperties)
{
List<ContentTransformer> transformers = new ArrayList<ContentTransformer>();
List<String> intermediateMimetypes = new ArrayList<String>();
extractTransformersAndMimetypes(property, transformers, intermediateMimetypes,
mimetypeService, transformerRegistry);
ComplexContentTransformer transformer = new ComplexContentTransformer()
{
@Override
public String getComments(boolean available)
{
return getCommentNameAndAvailable(true); // suppress the ...available=false line as it is reported anyway if set
}
};
setupContentTransformer2(property, transformerConfig, mimetypeService,
transformerRegistry, transformerDebug, available, transformer, transformers, globalProperties);
// baseComplexContentTransformer
transformer.setLegacySynchronousTransformClient(legacySynchronousTransformClient);
// ComplexContentTransformer
transformer.setTransformers(transformers);
transformer.setIntermediateMimetypes(intermediateMimetypes);
return transformer;
}
private AbstractContentTransformer2 createFailoverTransformer(TransformerSourceTargetSuffixValue property,
TransformerConfig transformerConfig,
MimetypeService mimetypeService,
ContentTransformerRegistry transformerRegistry, TransformerDebug transformerDebug,
boolean available, Properties globalProperties)
{
List<ContentTransformer> transformers = new ArrayList<ContentTransformer>();
extractTransformersAndMimetypes(property, transformers, null,
mimetypeService, transformerRegistry);
FailoverContentTransformer transformer = new FailoverContentTransformer()
{
@Override
public String getComments(boolean available)
{
return getCommentNameAndAvailable(true); // suppress the ...available=false line as it is reported anyway if set
}
};
setupContentTransformer2(property, transformerConfig, mimetypeService,
transformerRegistry, transformerDebug, available, transformer, transformers, globalProperties);
// FailoverContentTransformer
transformer.setTransformers(transformers);
return transformer;
}
/**
* Populates transformers and intermediateMimetypes (optional) from the supplied property value.
* @throws AlfrescoRuntimeException if the value is invalid
* @throws IllegalArgumentException if sub-transformer does not exist
*/
private void extractTransformersAndMimetypes(TransformerSourceTargetSuffixValue property,
List<ContentTransformer> transformers, List<String> intermediateMimetypes,
MimetypeService mimetypeService, ContentTransformerRegistry transformerRegistry)
{
String[] subTransformersAndMimetypes = property.value.split("\\"+PIPE);
boolean hasMimetypes = intermediateMimetypes != null;
if ((!hasMimetypes && subTransformersAndMimetypes.length < 2) ||
(hasMimetypes && (subTransformersAndMimetypes.length < 3 || subTransformersAndMimetypes.length%2 == 0)))
{
throw new AlfrescoRuntimeException("Cannot create dynamic transformer "+
property.transformerName+" as the value "+property.value+" has the wrong number of components.");
}
boolean isTransformerName = true;
for (String name: subTransformersAndMimetypes)
{
if (isTransformerName)
{
try
{
ContentTransformer subTransformer = TransformerConfig.ANY.equals(name)
? null
// throws IllegalArgumentException if sub-transformer does not exist
: transformerRegistry.getTransformer(TransformerConfig.TRANSFORMER+name);
transformers.add(subTransformer);
}
catch (IllegalArgumentException e)
{
logger.trace(property.transformerName+" did not find "+TransformerConfig.TRANSFORMER+name);
throw e;
}
}
else
{
String mimetype = mimetypeService.getMimetype(name);
if (!MimetypeMap.EXTENSION_BINARY.equals(name) && MimetypeMap.MIMETYPE_BINARY.equals(mimetype))
{
throw new AlfrescoRuntimeException("Cannot create dynamic transformer "+
property.transformerName+" as the extension "+name+" is unregistered.");
}
intermediateMimetypes.add(mimetype);
}
if (hasMimetypes)
{
isTransformerName = !isTransformerName;
}
}
}
// Set properties common to ComplexContentTransformer and FailoverContentTransformer.
private void setupContentTransformer2(TransformerSourceTargetSuffixValue property,
TransformerConfig transformerConfig, MimetypeService mimetypeService,
ContentTransformerRegistry transformerRegistry,
TransformerDebug transformerDebug, boolean available,
AbstractContentTransformer2 transformer, List<ContentTransformer> transformers,
Properties globalProperties)
{
try
{
// Throws an exception if it does not exist
transformerRegistry.getTransformer(property.transformerName);
throw new AlfrescoRuntimeException("Cannot create dynamic transformer "+
property.transformerName+" as a transformer with that name already exists.");
}
catch (IllegalArgumentException e)
{
// good news it does not exist
}
// unregisteredBaseContentTransformer
transformer.setMimetypeService(mimetypeService);
transformer.setTransformerDebug((LegacyTransformerDebug)transformerDebug);
transformer.setTransformerConfig(transformerConfig);
transformer.setRegistry(transformerRegistry);
// baseContentTransformer
transformer.setRegisterTransformer(true);
// AbstractContentTransformer2
transformer.setBeanName(property.transformerName);
transformer.setRegisterTransformer(available);
transformer.setStrictMimeTypeCheck(getBoolean(globalProperties, "transformer.strict.mimetype.check"));
transformer.setRetryTransformOnDifferentMimeType(getBoolean(globalProperties, "content.transformer.retryOn.different.mimetype"));
}
private boolean getBoolean(Properties properties, String name)
{
String value = properties == null ? null : properties.getProperty(name);
return "true".equalsIgnoreCase(value);
}
private void error(String msg)
{
errorCount++;
logger.error(msg);
}
int getErrorCount()
{
return errorCount;
}
public void removeTransformers(ContentTransformerRegistry transformerRegistry)
{
for (ContentTransformer transformer: dynamicTransformers)
{
transformerRegistry.removeTransformer(transformer);
}
}
}

View File

@@ -1,486 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory;
import org.alfresco.repo.rendition2.LegacySynchronousTransformClient;
import org.alfresco.service.cmr.module.ModuleService;
import org.alfresco.service.cmr.repository.MalformedNodeRefException;
import org.alfresco.service.cmr.repository.MimetypeService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.TransformationOptionLimits;
import org.alfresco.service.cmr.repository.TransformationOptions;
import org.alfresco.service.descriptor.DescriptorService;
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
*
* @deprecated The RenditionService is being replace by the simpler async RenditionService2.
*/
@Deprecated
public class TransformerConfigImpl extends AbstractLifecycleBean implements TransformerConfig
{
private static final Log logger = LogFactory.getLog(TransformerConfigImpl.class);
private MimetypeService mimetypeService;
private LegacySynchronousTransformClient legacySynchronousTransformClient;
private ContentTransformerRegistry transformerRegistry;
private TransformerDebug transformerDebug;
// Log
private TransformerLog transformerLog;
// Log Debug
private TransformerDebugLog transformerDebugLog;
// 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;
// Blacklist
private TransformerConfigProperty blacklist;
// 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;
private TransformerPropertySetter propertySetter;
// Needed to read properties.
private ChildApplicationContextFactory subsystemFactory;
// Needed to read global properties.
private Properties globalProperties;
private ModuleService moduleService;
private DescriptorService descriptorService;
private TransformerProperties transformerProperties;
private TransformerConfigDynamicTransformers dynamicTransformers;
private Map<String, Set<String>> strictMimetypeExceptions;
/**
* Sets of the mimetype service.
*
* @param mimetypeService
*/
public void setMimetypeService(MimetypeService mimetypeService)
{
this.mimetypeService = mimetypeService;
}
public void setLegacySynchronousTransformClient(LegacySynchronousTransformClient legacySynchronousTransformClient)
{
this.legacySynchronousTransformClient = legacySynchronousTransformClient;
}
public void setContentTransformerRegistry(ContentTransformerRegistry transformerRegistry)
{
this.transformerRegistry = transformerRegistry;
}
public void setTransformerDebug(TransformerDebug transformerDebug)
{
this.transformerDebug = transformerDebug;
}
public void setTransformerLog(TransformerLog transformerLog)
{
this.transformerLog = transformerLog;
}
public void setTransformerDebugLog(TransformerDebugLog transformerDebugLog)
{
this.transformerDebugLog = transformerDebugLog;
}
public void setGlobalProperties(Properties globalProperties)
{
this.globalProperties = globalProperties;
}
public void setModuleService(ModuleService moduleService)
{
this.moduleService = moduleService;
}
public void setDescriptorService(DescriptorService descriptorService)
{
this.descriptorService = descriptorService;
}
/**
* Called by spring after bean is initialised.
*/
public void initialise()
{
ChildApplicationContextFactory subsystem = getSubsystem();
transformerProperties = new TransformerProperties(subsystem, globalProperties);
dynamicTransformers = new TransformerConfigDynamicTransformers(this, transformerProperties, mimetypeService,
legacySynchronousTransformClient, transformerRegistry, transformerDebug, moduleService, descriptorService, globalProperties);
statistics= new TransformerConfigStatistics(this, mimetypeService);
limits = new TransformerConfigLimits(transformerProperties, mimetypeService);
supported = new TransformerConfigSupported(transformerProperties, mimetypeService);
priorities = new TransformerConfigProperty(transformerProperties, mimetypeService, PRIORITY, Integer.toString(PRIORITY_DEFAULT));
blacklist = new TransformerConfigProperty(transformerProperties, mimetypeService, BLACKLIST, "");
thresholdCounts = new TransformerConfigProperty(transformerProperties, mimetypeService, THRESHOLD_COUNT, "3");
errorTimes = new TransformerConfigProperty(transformerProperties, mimetypeService, ERROR_TIME, "120000");
initialAverageTimes = new TransformerConfigProperty(transformerProperties, mimetypeService, INITIAL_TIME, "0");
initialCounts = new TransformerConfigProperty(transformerProperties, mimetypeService, INITIAL_COUNT, "100000");
propertySetter = new TransformerPropertySetter(transformerProperties, mimetypeService, transformerRegistry);
strictMimetypeExceptions = getStrictMimetypeExceptions(transformerProperties);
}
/**
* Returns the 'transformers' subsystem which among other things holds transformer properties.
*/
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)
{
dynamicTransformers.removeTransformers(transformerRegistry);
}
/**
* {@inheritDoc}
*/
@Override
public String getProperty(String name)
{
return transformerProperties.getProperty(name);
}
@Override
public String getProperties(boolean changesOnly)
{
return new TransformerPropertyGetter(changesOnly, transformerProperties, mimetypeService,
transformerRegistry, transformerLog, transformerDebugLog).toString();
}
/**
* {@inheritDoc}
*/
@Override
public int setProperties(String propertyNamesAndValues)
{
return propertySetter.setProperties(propertyNamesAndValues);
}
@Override
public int removeProperties(String propertyNames)
{
return propertySetter.removeProperties(propertyNames);
}
/**
* {@inheritDoc}
*/
@Override
public TransformerStatistics getStatistics(ContentTransformer transformer, String sourceMimetype, String targetMimetype, boolean createNew)
{
return statistics.getStatistics(transformer, stdMimetype(sourceMimetype), stdMimetype(targetMimetype), createNew);
}
/**
* {@inheritDoc}
*/
@Override
public TransformationOptionLimits getLimits(ContentTransformer transformer, String sourceMimetype,
String targetMimetype, String use)
{
return limits.getLimits(transformer, stdMimetype(sourceMimetype), stdMimetype(targetMimetype), use);
}
/**
* {@inheritDoc}
*/
@Override
public boolean isSupportedTransformation(ContentTransformer transformer, String sourceMimetype,
String targetMimetype, TransformationOptions options)
{
return supported.isSupportedTransformation(transformer, stdMimetype(sourceMimetype), stdMimetype(targetMimetype), options);
}
/**
* {@inheritDoc}
*/
@Override
public int getPriority(ContentTransformer transformer, String sourceMimetype, String targetMimetype)
{
try
{
return priorities.getInt(transformer, stdMimetype(sourceMimetype), stdMimetype(targetMimetype));
}
catch (NumberFormatException e1)
{
try
{
return priorities.getInt(null, null, null);
}
catch (NumberFormatException e2)
{
return 0;
}
}
}
/**
* {@inheritDoc}
*/
@Override
public List<NodeRef> getBlacklist(ContentTransformer transformer, String sourceMimetype, String targetMimetype)
{
try
{
return blacklist.getNodeRefs(transformer, stdMimetype(sourceMimetype), stdMimetype(targetMimetype));
}
catch (MalformedNodeRefException e1)
{
try
{
return priorities.getNodeRefs(null, null, null);
}
catch (MalformedNodeRefException e2)
{
return null;
}
}
}
// Build up a Map keyed on declared source node mimetype to a Set of detected mimetypes that should allow
// the transformation to take place. i.e. The cases that Tika gets wrong.
private Map<String, Set<String>> getStrictMimetypeExceptions(TransformerProperties transformerProperties2)
{
Map<String, Set<String>> strictMimetypeExceptions = new HashMap<>();
String whitelist = getProperty(STRICT_MIMETYPE_CHECK_WHITELIST_MIMETYPES);
whitelist = whitelist == null ? "" : whitelist.trim();
if (whitelist.length() > 0)
{
String[] mimetypes = whitelist.split(";");
if (mimetypes.length % 2 != 0)
{
logger.error(STRICT_MIMETYPE_CHECK_WHITELIST_MIMETYPES+" should have an even number of mimetypes as a ; separated list.");
}
else
{
Set<String> detectedMimetypes = null;
for (String mimetype: mimetypes)
{
mimetype = mimetype.trim();
if (mimetype.isEmpty())
{
logger.error(STRICT_MIMETYPE_CHECK_WHITELIST_MIMETYPES+" contains a blank mimetype.");
// Still okay to use it in the map though, but it will be ignored.
}
if (detectedMimetypes == null)
{
detectedMimetypes = strictMimetypeExceptions.get(mimetype);
if (detectedMimetypes == null)
{
detectedMimetypes = new HashSet<>();
strictMimetypeExceptions.put(mimetype, detectedMimetypes);
}
}
else
{
detectedMimetypes.add(mimetype);
detectedMimetypes = null;
}
}
}
}
return strictMimetypeExceptions;
}
/**
* {@inheritDoc}
*/
@Override
public boolean strictMimetypeCheck(String declaredMimetype, String detectedMimetype)
{
if (detectedMimetype == null)
{
return true;
}
Set<String> detectedMimetypes = strictMimetypeExceptions.get(declaredMimetype);
return detectedMimetypes != null && detectedMimetypes.contains(detectedMimetype);
}
/**
* {@inheritDoc}
*/
@Override
public int getThresholdCount(ContentTransformer transformer, String sourceMimetype, String targetMimetype)
{
try
{
return thresholdCounts.getInt(transformer, stdMimetype(sourceMimetype), stdMimetype(targetMimetype));
}
catch (NumberFormatException e1)
{
try
{
return thresholdCounts.getInt(null, null, null);
}
catch (NumberFormatException e2)
{
return 0;
}
}
}
/**
* Gets the time to be recorded if there is an error.
*/
long getErrorTime(ContentTransformer transformer, String sourceMimetype, String targetMimetype)
{
try
{
return errorTimes.getLong(transformer, stdMimetype(sourceMimetype), stdMimetype(targetMimetype));
}
catch (NumberFormatException e1)
{
try
{
return errorTimes.getInt(null, null, null);
}
catch (NumberFormatException e2)
{
return 0;
}
}
}
/**
* 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)
{
try
{
return initialAverageTimes.getLong(transformer, stdMimetype(sourceMimetype), stdMimetype(targetMimetype));
}
catch (NumberFormatException e1)
{
try
{
return initialAverageTimes.getInt(null, null, null);
}
catch (NumberFormatException e2)
{
return 0;
}
}
}
/**
* 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)
{
try
{
return initialCounts.getInt(transformer, stdMimetype(sourceMimetype), stdMimetype(targetMimetype));
}
catch (NumberFormatException e1)
{
try
{
return initialCounts.getInt(null, null, null);
}
catch (NumberFormatException e2)
{
return 0;
}
}
}
// Returns the main or standard mimetype. Needed were multiple mimetypes share the same extension or are unknown so binary.
private String stdMimetype(String mimetype)
{
return mimetypeService.getMimetype(mimetypeService.getExtension(mimetype));
}
}

View File

@@ -1,434 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import static org.alfresco.repo.content.transform.TransformerConfig.ANY;
import static org.alfresco.repo.content.transform.TransformerConfig.DEFAULT_TRANSFORMER;
import static org.alfresco.repo.content.transform.TransformerConfig.LIMIT_SUFFIXES;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import org.alfresco.service.cmr.repository.MimetypeService;
import org.alfresco.service.cmr.repository.TransformationOptionLimits;
import org.alfresco.service.cmr.repository.TransformationOptionPair;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Provides access to transformer limits defined via properties.
*
* @author Alan Davis
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public class TransformerConfigLimits extends TransformerPropertyNameExtractor
{
private static Log logger = LogFactory.getLog(TransformerConfigLimits.class);
private static final String NOT_THROWN_MESSAGE = "Both max and limit should not be set.";
// Map using use, transformer, source mimetype and target mimetype to a set of limits.
// Entries higher up the hierarchy are added so that values may be defaulted down.
// Entries are added lower down the hierarchy when a search takes place.
private Map<String, Map<String, DoubleMap<String, String, TransformationOptionLimits>>> limitsMap;
// The 'use' value that had properties defined, including ANY for the default.
private Set<String> uses;
public TransformerConfigLimits(TransformerProperties transformerProperties, MimetypeService mimetypeService)
{
setLimits(transformerProperties, mimetypeService);
}
/**
* Sets the transformer limits created from properties.
*/
private void setLimits(TransformerProperties transformerProperties, MimetypeService mimetypeService)
{
limitsMap = new ConcurrentHashMap<String, Map<String, DoubleMap<String, String, TransformationOptionLimits>>>();
uses = new HashSet<String>();
// Gets all the transformer, source and target combinations in properties that define limits.
Map<TransformerSourceTargetSuffixKey, TransformerSourceTargetSuffixValue> allUseMap =
getTransformerSourceTargetValuesMap(LIMIT_SUFFIXES, true, true, true, transformerProperties, mimetypeService);
// Get the set 'use' values.
uses.add(ANY);
for (TransformerSourceTargetSuffixValue property: allUseMap.values())
{
String propertyUse = property.use == null ? ANY : property.use;
uses.add(propertyUse);
}
// Populate the limitsMap for each 'use'.
for (String use: uses)
{
Collection<TransformerSourceTargetSuffixValue> properties = getPropertiesForUse(use, allUseMap);
// Add the system wide default just in case it is not included, as we always need this one
getOrCreateTransformerOptionLimits(DEFAULT_TRANSFORMER, ANY, ANY, use);
TransformationOptionLimits limits;
for (int pass=0; pass<=3; pass++)
{
for (TransformerSourceTargetSuffixValue property1: properties)
{
int origLevel = getLevel(property1.transformerName, property1.sourceMimetype);
if (pass == origLevel)
{
logger.debug(property1);
String transformerName = (property1.transformerName == null)
? DEFAULT_TRANSFORMER : property1.transformerName;
limits = getOrCreateTransformerOptionLimits(transformerName,
property1.sourceMimetype, property1.targetMimetype, use);
setTransformationLimitsFromProperties(limits, property1.value, property1.suffix);
debug("V", transformerName, property1.sourceMimetype, property1.targetMimetype, use, limits);
}
}
}
}
logger.debug(this);
}
/**
* Sets the transformer limits for a single use from properties. Method extracted so that
* it is possible to write a simpler unit test, that changes to the order of the
* properties. The order changed between Java 6, 7 and 8, resulting in MNT-14295. The original
* outer method cannot be used as it creates the list from a map (allUseMap) that it also
* creates and the order of values from that map cannot be controlled from a test.
*/
void setLimits(String use, Collection<TransformerSourceTargetSuffixValue> properties)
{
// Add the system wide default just in case it is not included, as we always need this one
getOrCreateTransformerOptionLimits(DEFAULT_TRANSFORMER, ANY, ANY, use);
TransformationOptionLimits limits;
for (int pass=0; pass<=3; pass++)
{
for (TransformerSourceTargetSuffixValue property: properties)
{
int origLevel = getLevel(property.transformerName, property.sourceMimetype);
if (pass == origLevel)
{
logger.debug(property);
String transformerName = (property.transformerName == null)
? DEFAULT_TRANSFORMER : property.transformerName;
limits = getOrCreateTransformerOptionLimits(transformerName,
property.sourceMimetype, property.targetMimetype, use);
setTransformationLimitsFromProperties(limits, property.value, property.suffix);
debug("V", transformerName, property.sourceMimetype, property.targetMimetype, use, limits);
}
}
}
}
/**
* Returns the 'effective' properties for the given 'use'.
*
* These will be made up from the properties defined for that use plus default properties
* that don't have a matching use property, as long as there is not a matching use at a
* higher level.<p>
*
* <li>If there is a system wide property with the use value, all other properties without
* the same use value are ignored.</li>
* <li>If there is a transformer wide property with this use value, all other transformer
* wide properties for the same transformer without a use value are ignored.
* <li>If there is mimetype property with the use value, the default property for
* the same combination is ignored.</li>
* @param use value such as "doclib" or "index"
* @param allUseMap the complete set of transformer properties that includes blank and all
* use values.
* @return a set of properties for the specific use.
*/
private Collection<TransformerSourceTargetSuffixValue> getPropertiesForUse(String use,
Map<TransformerSourceTargetSuffixKey, TransformerSourceTargetSuffixValue> allUseMap)
{
Collection<TransformerSourceTargetSuffixValue> properties = new ArrayList<TransformerSourceTargetSuffixValue>();
boolean systemWideUse = false;
Set<String> transformerWideUse = new HashSet<>();
for (TransformerSourceTargetSuffixValue property: allUseMap.values())
{
String propertyUse = property.use == null ? ANY : property.use;
if (propertyUse.equals(use))
{
if (DEFAULT_TRANSFORMER.equals(property.transformerName))
{
systemWideUse = true;
break;
}
transformerWideUse.add(property.transformerName);
}
}
for (TransformerSourceTargetSuffixValue property: allUseMap.values())
{
String propertyUse = property.use == null ? ANY : property.use;
if (propertyUse.equals(use))
{
properties.add(property);
}
else if (!systemWideUse && propertyUse.equals(ANY))
{
if (DEFAULT_TRANSFORMER.equals(property.transformerName) ||
!transformerWideUse.contains(property.transformerName))
{
// If there is NOT a similar 'use' property...
if (getProperty(property.transformerName, property.sourceExt, property.targetExt,
property.suffix, use, allUseMap) == null)
{
properties.add(property);
}
}
}
}
return properties;
}
/**
* Returns the TransformationOptionLimits for the use, transformer and mimetype combination,
* creating and adding one if not already included.
*/
private TransformationOptionLimits getOrCreateTransformerOptionLimits(String transformerName,
String sourceMimetype, String targetMimetype, String use)
{
Map<String, DoubleMap<String, String, TransformationOptionLimits>> transformerLimits = limitsMap.get(use);
if (transformerLimits == null)
{
transformerLimits = new ConcurrentHashMap<String, DoubleMap<String, String, TransformationOptionLimits>>();
limitsMap.put(use, transformerLimits);
}
DoubleMap<String, String, TransformationOptionLimits> mimetypeLimits = transformerLimits.get(transformerName);
if (mimetypeLimits == null)
{
mimetypeLimits = new DoubleMap<String, String, TransformationOptionLimits>(ANY, ANY);
transformerLimits.put(transformerName, mimetypeLimits);
}
TransformationOptionLimits limits = mimetypeLimits.getNoWildcards(sourceMimetype, targetMimetype);
if (limits == null)
{
// Try the wildcard version, and use any match as the basis for a new entry
limits = mimetypeLimits.get(sourceMimetype, targetMimetype);
limits = newTransformationOptionLimits(transformerName, sourceMimetype, targetMimetype, limits, use);
mimetypeLimits.put(sourceMimetype, targetMimetype, limits);
}
else
{
debug("G", transformerName, sourceMimetype, targetMimetype, use, limits);
}
return limits;
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder();
for (Entry<String, Map<String, DoubleMap<String, String, TransformationOptionLimits>>> useEntry: limitsMap.entrySet())
{
for (Entry<String, DoubleMap<String, String, TransformationOptionLimits>> transformerEntry: useEntry.getValue().entrySet())
{
if (sb.length() > 0)
{
sb.append("\n");
}
sb.append(useEntry.getKey()).
append(", ").
append(transformerEntry.getKey()).
append(" =>\n").
append(transformerEntry.getValue());
}
}
return sb.toString();
}
/**
* Creates a new TransformationOptionLimits for the use, transformer and mimetype combination,
* defaulting values from lower levels.
* @param wildCardLimits if not null this is a limit found using a wildcard so should
* form the basis of the new object.
*/
private TransformationOptionLimits newTransformationOptionLimits(String transformerName,
String sourceMimetype, String targetMimetype, TransformationOptionLimits wildCardLimits,
String use)
{
int origLevel = getLevel(transformerName, sourceMimetype);
TransformationOptionLimits limits = new TransformationOptionLimits();
// Start at the most general limits and then override with more specific values so that
// defaults from the most general get used if there is not something more specific.
for (int level=0; level<origLevel; level++)
{
TransformationOptionLimits defaultLimits =
level < 2
? level == 0
? getOrCreateTransformerOptionLimits(DEFAULT_TRANSFORMER, ANY, ANY, use) // 0
: getOrCreateTransformerOptionLimits(DEFAULT_TRANSFORMER, sourceMimetype, targetMimetype, use) // 1
: level == 2
? getOrCreateTransformerOptionLimits(transformerName, ANY, ANY, use) // 2
: getOrCreateTransformerOptionLimits(transformerName, sourceMimetype, targetMimetype, use); // 3
defaultLimits.defaultTo(limits);
}
if (wildCardLimits != null)
{
wildCardLimits.defaultTo(limits);
}
debug("N", transformerName, sourceMimetype, targetMimetype, use, limits);
return limits;
}
private int getLevel(String transformerName, String sourceMimetype)
{
boolean defaultMimetypes = sourceMimetype == null || sourceMimetype.equals(ANY);
int level = transformerName == null || DEFAULT_TRANSFORMER.equals(transformerName)
? defaultMimetypes ? 0 : 1
: defaultMimetypes ? 2 : 3;
return level;
}
/**
* Sets a TransformationOptionLimits value. This may be a size in K bytes,
* a time in ms or number of pages. It may also be a maximum or limit value.
* When the maximum and limit are both set and the same, the maximum value
* wins.
*/
private void setTransformationLimitsFromProperties(TransformationOptionLimits limits,
String value, String suffix)
{
long newValue = Long.parseLong(value);
TransformationOptionPair optionPair =
suffix == TransformerConfig.MAX_SOURCE_SIZE_K_BYTES ||
suffix == TransformerConfig.READ_LIMIT_K_BYTES
? limits.getKBytesPair()
: suffix == TransformerConfig.TIMEOUT_MS ||
suffix == TransformerConfig.READ_LIMIT_TIME_MS
? limits.getTimePair()
: limits.getPagesPair();
// If max rather than limit value
if (suffix == TransformerConfig.MAX_SOURCE_SIZE_K_BYTES ||
suffix == TransformerConfig.TIMEOUT_MS ||
suffix == TransformerConfig.MAX_PAGES)
{
long limit = optionPair.getLimit();
if (limit < 0 || limit >= newValue)
{
optionPair.setLimit(-1, NOT_THROWN_MESSAGE);
optionPair.setMax(newValue, NOT_THROWN_MESSAGE);
}
}
else
{
long max = optionPair.getMax();
if (max < 0 || max > newValue)
{
optionPair.setMax(-1, NOT_THROWN_MESSAGE);
optionPair.setLimit(newValue, NOT_THROWN_MESSAGE);
}
}
}
private void debug(String msg, String transformerName, String sourceMimetype,
String targetMimetype, String use, TransformationOptionLimits limits)
{
if (logger.isDebugEnabled())
{
StringBuilder sb = new StringBuilder("");
if (msg != null)
{
int x = getLevel(transformerName, sourceMimetype);
sb.append(x);
sb.append(' ');
sb.append(msg);
for (; x>-1; x--)
{
sb.append(' ');
}
sb.append(transformerName);
sb.append('.');
sb.append(sourceMimetype);
sb.append('.');
sb.append(targetMimetype);
sb.append('.');
sb.append(use);
sb.append('=');
sb.append(limits);
}
String line = sb.toString();
logger.debug(line);
}
}
/**
* See {@link TransformerConfig#getLimits(ContentTransformer, String, String, String)}.
*/
public TransformationOptionLimits getLimits(ContentTransformer transformer, String sourceMimetype,
String targetMimetype, String use)
{
String transformerName = (transformer == null) ? DEFAULT_TRANSFORMER : transformer.getName();
if (sourceMimetype == null)
{
sourceMimetype = ANY;
}
if (targetMimetype == null)
{
targetMimetype = ANY;
}
if (use == null)
{
use = ANY;
}
debug(null, transformerName, sourceMimetype, targetMimetype, use, null);
String searchUse = uses.contains(use) ? use : ANY;
TransformationOptionLimits limits = getOrCreateTransformerOptionLimits(transformerName, sourceMimetype, targetMimetype, searchUse);
debug("S", transformerName, sourceMimetype, targetMimetype, use, limits);
return limits;
}
}

View File

@@ -30,48 +30,20 @@ package org.alfresco.repo.content.transform;
* and statistics.
*
* @author Alan Davis
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public interface TransformerConfigMBean
{
/**
* Lists the names of all top level transformers.
*/
public String[] getTransformerNames();
/**
* Lists all configured mimetypes, proceeded by its primary file extension.
*/
public String[] getExtensionsAndMimetypes();
/**
* Lists all possible transformations sorted by Transformer name.
* @param transformerName to be checked. If null all transformers are included.
* @param use or context in which the transformation will be used ("doclib",
* "index", "webpreview", "syncRule", "asyncRule"...) or null for the default.
*/
@Deprecated
public String getTransformationsByTransformer(String transformerName, String use);
/**
* Lists all possible transformations sorted by source and then target mimetype extension.
* @param sourceExtension to be checked. If null all source mimetypes are included.
* @param targetExtension to be checked. If null all target mimetypes are included.
* @param use or context in which the transformation will be used ("doclib",
* "index", "webpreview", "syncRule", "asyncRule"...) or null for the default.
*/
public String getTransformationsByExtension(String sourceExtension, String targetExtension, String use);
/**
* Lists the transformation statistics for the current node.
* @param transformerName to be checked. If null all transformers are included.
* @param sourceExtension to be checked. If null all source mimetypes are included.
* @param targetExtension to be checked. If null all target mimetypes are included.
*/
@Deprecated
public String getTransformationStatistics(String transformerName, String sourceExtension, String targetExtension);
public String getTransformationsByExtension(String sourceExtension, String targetExtension);
/**
* Returns the last n entries in the transformation log.
@@ -83,51 +55,14 @@ public interface TransformerConfigMBean
*/
public String[] getTransformationDebugLog(int n);
/**
* Returns custom and default transformer propertiest.
* @param listAll list both default and custom values, otherwise includes
* only custom values.
*/
@Deprecated
public String getProperties(boolean listAll);
/**
* Adds or replaces new transformer properties.
* @param propertyNamesAndValues
* @return a confirmation or failure message
*/
@Deprecated
public String setProperties(String propertyNamesAndValues);
/**
* Removes transformer properties.
* @param propertyNames to be removed. Any values after the property name are ignored.
* @return a confirmation or failure message
*/
@Deprecated
String removeProperties(String propertyNames);
/**
* Transforms a small test file from one mimetype to another and then shows the debug of the
* transform, which would indicate if it was successful or even if it was possible.
* @param transformerName to be used. If not specified the ContentService is used to select one.
* @param sourceExtension used to identify the mimetype
* @param targetExtension used to identify the mimetype
* @param use or context in which to test the transformation ("doclib", "index", "webpreview",
* "syncRule", "asyncRule"...) or blank for the default.";
* @return Text indicating if the transform was possible and any debug
*/
public String testTransform(String transformerName, String sourceExtension, String targetExtension, String use);
/**
* Lists the names of the contexts or uses.
*/
public String[] getContextNames();
/**
* Lists custom (non default) property names.
*/
public String[] getCustomePropertyNames();
public String testTransform(String sourceExtension, String targetExtension);
/**
* Lists the extensions of available test files.

View File

@@ -26,9 +26,7 @@
package org.alfresco.repo.content.transform;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import org.alfresco.service.cmr.repository.MimetypeService;
@@ -37,35 +35,20 @@ import org.alfresco.service.cmr.repository.MimetypeService;
* and statistics.
*
* @author Alan Davis
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public class TransformerConfigMBeanImpl implements TransformerConfigMBean
{
private static final String NO_TRANSFORMATIONS_TO_REPORT = "No transformations to report";
private ContentTransformerRegistry transformerRegistry;
private AdminUiTransformerDebug transformerDebug;
private TransformerConfig transformerConfig;
private MimetypeService mimetypeService;
private LogEntries transformerLog;
private LogEntries transformerDebugLog;
public void setContentTransformerRegistry(ContentTransformerRegistry transformerRegistry)
{
this.transformerRegistry = transformerRegistry;
}
public void setTransformerDebug(AdminUiTransformerDebug transformerDebug)
{
this.transformerDebug = transformerDebug;
}
public void setTransformerConfig(TransformerConfig transformerConfig)
{
this.transformerConfig = transformerConfig;
}
public void setMimetypeService(MimetypeService mimetypeService)
{
this.mimetypeService = mimetypeService;
@@ -81,22 +64,6 @@ public class TransformerConfigMBeanImpl implements TransformerConfigMBean
this.transformerDebugLog = transformerDebugLog;
}
@Override
public String[] getTransformerNames()
{
List<String> transformerNames = new ArrayList<String>();
Collection<ContentTransformer> transformers = ((LegacyTransformerDebug)transformerDebug).sortTransformersByName(null);
for (ContentTransformer transformer: transformers)
{
String name = transformer.getName();
name = name.startsWith(TransformerConfig.TRANSFORMER)
? name.substring(TransformerConfig.TRANSFORMER.length())
: name;
transformerNames.add(name);
}
return transformerNames.toArray(new String[transformerNames.size()]);
}
@Override
public String[] getExtensionsAndMimetypes()
{
@@ -110,18 +77,12 @@ public class TransformerConfigMBeanImpl implements TransformerConfigMBean
}
@Override
public String getTransformationsByTransformer(String simpleTransformerName, String use)
public String getTransformationsByExtension(String sourceExtension, String targetExtension)
{
use = nullDefaultParam(use);
try
{
// Need to be able to generate 4.1.4ish output to compare with previous
// releases without too much effort cutting and pasting to change the order
return "41".equals(simpleTransformerName)
? ((LegacyTransformerDebug)transformerDebug).transformationsByTransformer(
null, true, false, use)
: ((LegacyTransformerDebug)transformerDebug).transformationsByTransformer(
getTransformerNameParam(simpleTransformerName), true, true, use);
return transformerDebug.transformationsByExtension(nullDefaultLowerParam(sourceExtension),
nullDefaultLowerParam(targetExtension), true);
}
catch (IllegalArgumentException e)
{
@@ -129,141 +90,6 @@ public class TransformerConfigMBeanImpl implements TransformerConfigMBean
}
}
@Override
public String getTransformationsByExtension(String sourceExtension, String targetExtension, String use)
{
use = nullDefaultParam(use);
try
{
// 41: Need to be able to generate 4.1.4ish output to compare with previous
// releases without too much effort cutting and pasting to change the order
// 00: (prefix) Finds only non deterministic transformations
if ("41".equals(sourceExtension))
{
return transformerDebug.transformationsByExtension(null, null, true, false, false, null);
}
else
{
boolean onlyNonDeterministic = false;
if (sourceExtension != null && sourceExtension.startsWith("00"))
{
onlyNonDeterministic = true;
sourceExtension = sourceExtension.substring(2);
}
return transformerDebug.transformationsByExtension(nullDefaultLowerParam(sourceExtension),
nullDefaultLowerParam(targetExtension), true, true, onlyNonDeterministic, use);
}
}
catch (IllegalArgumentException e)
{
return e.getMessage();
}
}
@Override
public String getTransformationStatistics(String simpleTransformerName, String sourceExtension, String targetExtension)
{
try
{
StringBuilder sb = new StringBuilder();
String transformerName = getTransformerNameParam(simpleTransformerName);
sourceExtension = nullDefaultLowerParam(sourceExtension);
targetExtension = nullDefaultLowerParam(targetExtension);
Collection<ContentTransformer> transformers = ((LegacyTransformerDebug)transformerDebug).sortTransformersByName(transformerName);
Collection<String> sourceMimetypes = transformerDebug.getSourceMimetypes(sourceExtension);
Collection<String> targetMimetypes = transformerDebug.getTargetMimetypes(sourceExtension, targetExtension, sourceMimetypes);
// Only report system wide mimetype summary if transformer not specified
boolean includeSystemWideSummary = transformerName == null;
if (includeSystemWideSummary)
{
getTransformationStatistics(sourceExtension, targetExtension, sb,
null, sourceMimetypes, targetMimetypes, false);
}
for (ContentTransformer transformer: transformers)
{
getTransformationStatistics(sourceExtension, targetExtension, sb,
transformer, sourceMimetypes, targetMimetypes, includeSystemWideSummary);
}
if (sb.length() == 0)
{
sb.append(NO_TRANSFORMATIONS_TO_REPORT);
}
return sb.toString();
}
catch (IllegalArgumentException e)
{
return e.getMessage();
}
}
private void getTransformationStatistics(String sourceExtension, String targetExtension,
StringBuilder sb, ContentTransformer transformer, Collection<String> sourceMimetypes,
Collection<String> targetMimetypes, boolean includeSystemWideSummary)
{
AtomicInteger counter = new AtomicInteger(0);
int i = sb.length();
for (String sourceMimetype: sourceMimetypes)
{
for (String targetMimetype: targetMimetypes)
{
getTransformationStatistics(sb, transformer, sourceMimetype, targetMimetype, counter, includeSystemWideSummary);
}
}
// Only report transformer summary if there is more than one to summarise
// and we were asked for all
if (sourceExtension == null && targetExtension == null && counter.get() > 1)
{
StringBuilder sb2 = new StringBuilder();
getTransformationStatistics(sb2, transformer, null, null, counter, includeSystemWideSummary);
sb2.append('\n');
sb.insert((i == 0 ? 0 : i+2), sb2);
}
}
private void getTransformationStatistics(StringBuilder sb, ContentTransformer transformer,
String sourceMimetype, String targetMimetype, AtomicInteger counter,
boolean includeSystemWideSummary)
{
TransformerStatistics statistics = transformerConfig.getStatistics(transformer,
sourceMimetype, targetMimetype, false);
if (statistics != null)
{
long count = statistics.getCount();
if (count > 0)
{
if (sb.length() > 0)
{
sb.append('\n');
}
if (counter.incrementAndGet() == 1 && includeSystemWideSummary)
{
sb.append('\n');
}
sb.append(statistics.getTransformerName());
sb.append(' ');
sb.append(statistics.getSourceExt());
sb.append(' ');
sb.append(statistics.getTargetExt());
sb.append(" count=");
sb.append(count);
sb.append(" errors=");
sb.append(statistics.getErrorCount());
sb.append(" averageTime=");
sb.append(statistics.getAverageTime());
sb.append(" ms");
}
}
}
@Override
public String[] getTransformationLog(int n)
{
@@ -283,21 +109,11 @@ public class TransformerConfigMBeanImpl implements TransformerConfigMBean
}
@Override
public String getProperties(boolean listAll)
{
return transformerConfig.getProperties(!listAll);
}
@Override
public String setProperties(String propertyNamesAndValues)
public String testTransform(String sourceExtension, String targetExtension)
{
try
{
String nullPropertyNamesAndValues = nullDefaultParam(propertyNamesAndValues);
int n = nullPropertyNamesAndValues == null
? 0
: transformerConfig.setProperties(nullPropertyNamesAndValues);
return "Properties added or changed: "+n;
return transformerDebug.testTransform(sourceExtension, targetExtension);
}
catch (IllegalArgumentException e)
{
@@ -305,91 +121,12 @@ public class TransformerConfigMBeanImpl implements TransformerConfigMBean
}
}
@Override
public String removeProperties(String propertyNames)
{
try
{
propertyNames = nullDefaultParam(propertyNames);
return "Properties removed: "+
(propertyNames == null
? 0
: transformerConfig.removeProperties(propertyNames));
}
catch (IllegalArgumentException e)
{
return e.getMessage();
}
}
@Override
public String testTransform(final String simpleTransformerName, String sourceExtension,
String targetExtension, String use)
{
use = nullDefaultParam(use);
try
{
return transformerDebug.testTransform( sourceExtension, targetExtension, use);
}
catch (IllegalArgumentException e)
{
return e.getMessage();
}
}
@Override
public String[] getContextNames()
{
return new String[] {"", "doclib", "index", "webpreview", "syncRule", "asyncRule", "pdf"};
}
@Override
public String[] getCustomePropertyNames()
{
List<String> propertyNames = new ArrayList<String>();
String[] lines = getProperties(false).split("\\n");
for (String line: lines)
{
if (!line.isEmpty() && !line.startsWith("#") && line.indexOf(" # default=") == -1)
{
int i = line.indexOf('=');
if (i != 0)
{
String propertyName = line.substring(0, i);
propertyNames.add(propertyName);
}
}
}
return propertyNames.toArray(new String[propertyNames.size()]);
}
@Override
public String[] getTestFileExtensionsAndMimetypes()
{
return transformerDebug.getTestFileExtensionsAndMimetypes();
}
/**
* Returns a full transformer name given a simple transformer name parameter.
* @param simpleTransformerName the name of the transformer without the
* {@link TransformerConfig#TRANSFORMER} prefix.
* @return a null or a full transformer name
*/
private String getTransformerNameParam(String simpleTransformerName)
{
simpleTransformerName = nullDefaultParam(simpleTransformerName);
String transformerName = simpleTransformerName == null
? null
: simpleTransformerName.startsWith(TransformerConfig.TRANSFORMER)
? simpleTransformerName
: TransformerConfig.TRANSFORMER+simpleTransformerName;
// Throws an IllegalArgumentException if unknown
transformerRegistry.getTransformer(transformerName);
return transformerName;
}
/**
* Changes the default JConsole parameter value "String" (and the zero length
* String) to null and forces other values to lower case.
@@ -420,18 +157,7 @@ public class TransformerConfigMBeanImpl implements TransformerConfigMBean
@Override
public String help()
{
return "getProperties(listAll)\n" +
" Lists all transformer properties that are set.\n" +
" - listAll if true, list both default and custom values, otherwise includes\n" +
" only custom values\n" +
"\n" +
"setProperties(propertyNamesAndValues)\n" +
" Adds or replaces transformer properties.\n" +
" - propertyNamesAndValues to be set. May include comments but these are removed.\n" +
" To clear a custom values, set its value back to the default.\n" +
" To remove a custom property use removeProperties(...)\n" +
"\n" +
"getTransformationDebugLog(n)\n" +
return "getTransformationDebugLog(n)\n" +
" Lists the latest entries in the transformation debug log.\n" +
" - n the number of entries to include. If blank all available entries are listed\n" +
"\n" +
@@ -439,34 +165,19 @@ public class TransformerConfigMBeanImpl implements TransformerConfigMBean
" Lists the latest entries in the transformation log.\n" +
" - n the number of entries to include. If blank all available entries are listed\n" +
"\n" +
"getTransformationStatistics(transformerName, sourceExtension, targetExtension)\n" +
" Lists the transformation statistics for the current node.\n" +
" - transformerName to be checked. If blank all transformers are included\n" +
" - sourceExtension to be checked. If blank all source mimetypes are included\n" +
" - targetExtension to be checked. If blank all target mimetypes are included\n" +
"\n" +
"getExtensionsAndMimetypes()\n" +
" Lists all configured mimetypes and the primary file extension\n" +
"\n" +
"getTransformerNames()\n" +
" Lists the names of all top level transformers\n" +
"\n" +
"testTransform(transformerName, sourceExtension, targetExtension, use)\n" +
"testTransform(sourceExtension, targetExtension, use)\n" +
" Transforms a small test file from one mimetype to another and then shows the \n" +
" debug of the transform, which would indicate if it was successful or even if \n" +
" it was possible.\n" +
" - transformerName to be used. If blank the ContentService is used to select one.\n" +
" - sourceExtension used to identify the mimetype\n" +
" - targetExtension used to identify the mimetype\n" +
" - use or context in which to test the transformation (\"doclib\",\n" +
" \"index\", \"webpreview\", \"syncRule\", \"asyncRule\"...) or blank for\n" +
" the default.\n" +
"\n" +
"removeProperties(String propertyNames)\n" +
" Removes transformer properties.\n" +
" - propertyNames to be removed. May include =<value> after the property name.\n" +
" The value is ignored. Only custom properties should be removed.\n" +
"\n" +
"getTransformationsByExtension(sourceExtension, targetExtension, use)\n" +
" Lists all possible transformations sorted by source and then target mimetype\n" +
" extension.\n" +
@@ -476,19 +187,6 @@ public class TransformerConfigMBeanImpl implements TransformerConfigMBean
" \"index\", \"webpreview\", \"syncRule\", \"asyncRule\"...) or blank for\n" +
" the default.\n" +
"\n" +
"getTransformationsByTransformer(transformerName, use)\n" +
" Lists all possible transformations sorted by Transformer name\n" +
" - transformerName to be checked. If blank all transformers are included\n" +
" - use or context in which the transformation will be used (\"doclib\",\n" +
" \"index\", \"webpreview\", \"syncRule\", \"asyncRule\"...) or blank for\n" +
" the default.\n"+
"\n" +
"getCustomePropertyNames()\n" +
" Lists custom (non default) property names\n" +
"\n" +
"getContextNames()\n" +
" Lists the names of the contexts or uses\n" +
"\n" +
"getTestFileExtensionsAndMimetypes()\n" +
" Lists the extensions of available test files";
}

View File

@@ -1,151 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import static org.alfresco.repo.content.transform.TransformerConfig.ANY;
import static org.alfresco.repo.content.transform.TransformerConfig.DEFAULT_TRANSFORMER;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.service.cmr.repository.MalformedNodeRefException;
import org.alfresco.service.cmr.repository.MimetypeService;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* Provides access to a single transformer configuration property depending on the
* transformer and source and target mimetypes, falling back to defaults.
*
* @author Alan Davis
*
* @deprecated The RenditionService is being replace by the simpler async RenditionService2.
*/
@Deprecated
public class TransformerConfigProperty extends TransformerPropertyNameExtractor
{
private Map<String, DoubleMap<String, String, String>> values;
public TransformerConfigProperty(TransformerProperties transformerProperties,
MimetypeService mimetypeService, String propertySuffix, String defaultValue)
{
setValues(transformerProperties, mimetypeService, propertySuffix, defaultValue);
}
/**
* Sets the transformer values created from system properties.
*/
private void setValues(TransformerProperties transformerProperties, MimetypeService mimetypeService,
String suffix, String defaultValue)
{
values = new HashMap<String, DoubleMap<String, String, String>>();
// Gets all the transformer, source and target combinations in properties that define
// this value.
Map<TransformerSourceTargetSuffixKey, TransformerSourceTargetSuffixValue> properties =
getTransformerSourceTargetValuesMap(Collections.singletonList(suffix), true, true, false, transformerProperties, mimetypeService);
// Add the system wide default if it does not exist, as we always need this one
TransformerSourceTargetSuffixValue transformerSourceTargetValue =
new TransformerSourceTargetSuffixValue(DEFAULT_TRANSFORMER, ANY, ANY, suffix, null, defaultValue, mimetypeService);
TransformerSourceTargetSuffixKey key = transformerSourceTargetValue.key();
if (!properties.containsKey(key))
{
properties.put(key, transformerSourceTargetValue);
}
// Populate the transformer values
for (TransformerSourceTargetSuffixValue property: properties.values())
{
DoubleMap<String, String, String> mimetypeValues = values.get(property.transformerName);
if (mimetypeValues == null)
{
mimetypeValues = new DoubleMap<String, String, String>(ANY, ANY);
values.put(property.transformerName, mimetypeValues);
}
mimetypeValues.put(property.sourceMimetype, property.targetMimetype, property.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<String, String, String> 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)
throws NumberFormatException
{
return Long.parseLong(getString(transformer, sourceMimetype, targetMimetype));
}
public int getInt(ContentTransformer transformer, String sourceMimetype, String targetMimetype)
throws NumberFormatException
{
return Integer.parseInt(getString(transformer, sourceMimetype, targetMimetype));
}
public List<NodeRef> getNodeRefs(ContentTransformer transformer, String sourceMimetype, String targetMimetype)
throws MalformedNodeRefException
{
List<NodeRef> nodeRefs = new ArrayList<>();
String[] nodeRefStrings = getString(transformer, sourceMimetype, targetMimetype).split(", *");
for (String nodeRefString: nodeRefStrings)
{
nodeRefString = nodeRefString.trim();
if (nodeRefString.length() > 0)
{
NodeRef nodeRef = new NodeRef(nodeRefString);
nodeRefs.add(nodeRef);
}
}
return nodeRefs;
}
}

View File

@@ -1,138 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
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 statistics about:
* a) the combination of transformer, source and target mimetype;
* b) a summary for each transformer;
* c) a summary of top level transformations (++) for each combination of
* source and target mimetype;
* d) a summary of all top level transformations.
* These values are not shared across the cluster but are node specific.<p>
*
* ++ Top level transformations don't include transformations performed as part
* of another transformation.
*
* @author Alan Davis
*
* @deprecated The RenditionService is being replace by the simpler async RenditionService2.
*/
@Deprecated
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<String, DoubleMap<String, String, TransformerStatistics>> statistics =
new HashMap<String, DoubleMap<String, String, TransformerStatistics>>();
public TransformerConfigStatistics(TransformerConfigImpl transformerConfigImpl,
MimetypeService mimetypeService)
{
this.transformerConfigImpl = transformerConfigImpl;
this.mimetypeService = mimetypeService;
}
public TransformerStatistics getStatistics(ContentTransformer transformer, String sourceMimetype, String targetMimetype, boolean createNew)
{
if (sourceMimetype == null)
{
sourceMimetype = ANY;
}
if (targetMimetype == null)
{
targetMimetype = ANY;
}
TransformerStatistics transformerStatistics;
String name = (transformer == null) ? SUMMARY_TRANSFORMER_NAME : transformer.getName();
DoubleMap<String, String, TransformerStatistics> mimetypeStatistics = statistics.get(name);
if (!createNew)
{
transformerStatistics = (mimetypeStatistics == null)
? null
: mimetypeStatistics.getNoWildcards(sourceMimetype, targetMimetype);
return transformerStatistics;
}
if (mimetypeStatistics == null)
{
// Create the summary for the transformer as a whole
mimetypeStatistics = new DoubleMap<String, String, TransformerStatistics>(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 it 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;
}
}

View File

@@ -1,153 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import static org.alfresco.repo.content.transform.TransformerConfig.ANY;
import static org.alfresco.repo.content.transform.TransformerConfig.SUPPORTED;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.service.cmr.repository.MimetypeService;
import org.alfresco.service.cmr.repository.TransformationOptions;
/**
* Provides access to the lists of supported and unsupported mimetype transformations
* defined via properties for all transformers.
*
* @author Alan Davis
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
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<String, SupportedAndUnsupportedTransformations> supported;
public TransformerConfigSupported(TransformerProperties transformerProperties, MimetypeService mimetypeService)
{
setSupported(transformerProperties, mimetypeService);
}
/**
* Sets the supported/unsupported mimetype transformations created from system properties.
*/
private void setSupported(TransformerProperties transformerProperties, MimetypeService mimetypeService)
{
supported = new HashMap<String, SupportedAndUnsupportedTransformations>();
// Gets all the supported and unsupported transformer, source and target combinations
Collection<TransformerSourceTargetSuffixValue> properties =
getTransformerSourceTargetValues(Collections.singletonList(SUPPORTED),
false, false, transformerProperties, mimetypeService);
// Populate the transformer values
for (TransformerSourceTargetSuffixValue property: properties)
{
SupportedAndUnsupportedTransformations supportedBytransformer = this.supported.get(property.transformerName);
if (supportedBytransformer == null)
{
supportedBytransformer = new SupportedAndUnsupportedTransformations();
this.supported.put(property.transformerName, supportedBytransformer);
}
boolean supported = property.value == null || property.value.equalsIgnoreCase("true");
supportedBytransformer.put(property.sourceMimetype, property.targetMimetype, supported);
}
}
/**
* 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;
}
private class SupportedAndUnsupportedTransformations
{
DoubleMap<String, String, Boolean> supportedTransformations;
boolean supportedSet = false;
SupportedAndUnsupportedTransformations()
{
}
public void put(String sourceMimetype, String targetMimetype, boolean supported)
{
if (supportedTransformations == null)
{
supportedTransformations = new DoubleMap<String, String, Boolean>(ANY, ANY);
}
supportedTransformations.put(sourceMimetype, targetMimetype, supported);
if (supported)
{
supportedSet = true;
}
}
boolean isSupported(String sourceMimetype, String targetMimetype)
{
// To be backward compatible, the default (ANY to ANY) transformation
// needs to be true if only unsupported values are set or neither
// unsupported nor supported values are set. If supported values are
// set the default is false.
boolean isSupported = !supportedSet;
if (supportedTransformations != null)
{
Boolean sup = supportedTransformations.get(sourceMimetype, targetMimetype);
if (sup != null)
{
isSupported = sup;
}
}
return isSupported;
}
}
}

View File

@@ -56,7 +56,6 @@ import static org.alfresco.repo.rendition2.RenditionDefinition2.TIMEOUT;
* messages include a prefix to identify the transformation. A numeric dot notation
* is used (such as {@code 123.1.2} indicating the second third level transformation
* of the 123rd top level transformation).
*
* @author Alan Davis
*/
public class TransformerDebug

View File

@@ -38,10 +38,7 @@ import org.apache.commons.logging.Log;
* {@link TransformerConfigMBean#getTransformationDebugLog(int)}.<p>
*
* @author Alan Davis
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public class TransformerDebugLog extends TransformerLogger<DebugEntry>
{
private static Pattern END_OF_REQUEST_ID_PATTERN = Pattern.compile("[^0-9]");
@@ -63,7 +60,7 @@ public class TransformerDebugLog extends TransformerLogger<DebugEntry>
@Override
protected String getPropertyName()
{
return TransformerConfig.DEBUG_ENTRIES;
return "transformer.debug.entries";
}
@Override
@@ -108,7 +105,6 @@ public class TransformerDebugLog extends TransformerLogger<DebugEntry>
}
// Collects multiple lines of debug for the same transformer request.
@Deprecated
class DebugEntry
{
final String requestId;

View File

@@ -1,57 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import org.alfresco.error.AlfrescoRuntimeException;
/**
*
* Wraps an exception that could be thrown in any transformer to
* propagate it up to <code>NodeInfoBean.sendNodeInfo</code> method.
* <code>NodeInfoBean</code> can handle this exception to display it in NodeInfo frame
* to avoid error message box with "Exception in Transaction" message.
*
* See {@link org.alfresco.repo.content.transform.PoiHssfContentTransformer} for pattern.
*
* @author Arseny Kovalchuk
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public class TransformerInfoException extends AlfrescoRuntimeException
{
private static final long serialVersionUID = -4343331677825559617L;
public TransformerInfoException(String msg)
{
super(msg);
}
public TransformerInfoException(String msg, Throwable err)
{
super(msg, err);
}
}

View File

@@ -37,10 +37,7 @@ import org.alfresco.api.AlfrescoPublicApi;
* {@link TransformerConfigMBean#getTransformationLog(int)}.<p>
*
* @author Alan Davis
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
@AlfrescoPublicApi
public class TransformerLog extends TransformerLogger<String>
{
@@ -60,7 +57,7 @@ public class TransformerLog extends TransformerLogger<String>
@Override
protected String getPropertyName()
{
return TransformerConfig.LOG_ENTRIES;
return "transformer.log.entries";
}
@Override

View File

@@ -42,17 +42,14 @@ import org.apache.commons.logging.Log;
* Only supports debug level logging.
*
* @author Alan Davis
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
@AlfrescoPublicApi
abstract class TransformerLogger<T> extends LogAdapter implements LogEntries
{
static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("d MMM yyyy HH:mm:ss");
private TransformerDebug transformerDebug;
private TransformerConfig transformerConfig;
private Properties properties;
private int maxEntries = -1;
private Deque<T> entries = new LinkedList<T>();
@@ -67,22 +64,19 @@ abstract class TransformerLogger<T> extends LogAdapter implements LogEntries
this.transformerDebug = transformerDebug;
}
/**
* @param transformerConfig used to access the property.
*/
public void setTransformerConfig(TransformerConfig transformerConfig)
public void setProperties(Properties properties)
{
this.transformerConfig = transformerConfig;
this.properties = properties;
}
/**
* Returns an int from a property.
* @param propertyName
*/
private int getProperty(TransformerConfig transformerConfig, String propertyName, int min, int max)
private int getProperty(String propertyName, int min, int max)
{
int i = 0;
String value = transformerConfig.getProperty(propertyName);
String value = properties.getProperty(propertyName);
if (value != null)
{
try
@@ -106,7 +100,7 @@ abstract class TransformerLogger<T> extends LogAdapter implements LogEntries
{
if (maxEntries < 0)
{
maxEntries = getProperty(transformerConfig, getPropertyName(), 0, getUpperMaxEntries());
maxEntries = getProperty(getPropertyName(), 0, getUpperMaxEntries());
}
return maxEntries;
}
@@ -185,26 +179,22 @@ abstract class TransformerLogger<T> extends LogAdapter implements LogEntries
}
}
/**
* The transformer property and value used to set this logger. This is commented
* out if the property has not been overridden (default is 0).
* @param defaultProperties the transformer.properties file values that may be overridden.
* @return the transformer property and value.
*/
public String getPropertyAndValue(Properties defaultProperties)
private static void appendProperty(StringBuilder sb, String propertyName, String value, String defaultValue)
{
getMaxEntries();
String value = Integer.toString(maxEntries);
String propertyName = getPropertyName();
String defaultValue = defaultProperties == null ? null : defaultProperties.getProperty(propertyName);
defaultValue = defaultValue == null ? "0" : defaultValue;
StringBuilder sb = new StringBuilder();
TransformerPropertyGetter.appendProperty(sb, propertyName, value, defaultValue);
return sb.toString();
boolean isDefaultValue = value.equals(defaultValue);
if (isDefaultValue)
{
sb.append("# ");
}
sb.append(propertyName);
sb.append('=');
sb.append(value);
if (!isDefaultValue)
{
sb.append(" # default=");
sb.append(defaultValue);
}
}
/**
* Overridden to specify the maximum value the maxEntries property may set.
* Generally quite a small number as values are stored in memory.

View File

@@ -1,160 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Provides access to transformer properties which come from the Transformer sub system AND
* the those that start with "content.transformer." in the parent context.<p>
*
* By default a subsystem only provides properties defined within itself and only those
* properties may be overridden by alfresco.global.properties. New properties may not be added.
* As this class allows this to happen for the Transformers subsystem.
*
* @author Alan Davis
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public class TransformerProperties
{
private static final String TRANSFORMERS_PROPERTIES = "alfresco/subsystems/Transformers/default/transformers.properties";
private static Log logger = LogFactory.getLog(TransformerProperties.class);
private static final String JOD_CONVERTER = ".JodConverter.";
private static final String OPEN_OFFICE = ".OpenOffice.";
private final ChildApplicationContextFactory subsystem;
private final Properties globalProperties;
TransformerProperties(ChildApplicationContextFactory subsystem, Properties globalProperties)
{
this.subsystem = subsystem;
this.globalProperties = globalProperties;
}
public String getProperty(String name)
{
String value = subsystem.getProperty(name);
if (value == null)
{
value = globalProperties.getProperty(name);
if (value == null)
{
name = alias(name, JOD_CONVERTER, OPEN_OFFICE);
value = globalProperties.getProperty(name);
}
}
return value;
}
/**
* Returns the default properties from the transformers.properties file. These may be overridden by customers in
* other property files and JMX.
*/
public Properties getDefaultProperties()
{
Properties defaultProperties = new Properties();
InputStream propertiesStream = getClass().getClassLoader().getResourceAsStream(TRANSFORMERS_PROPERTIES);
if (propertiesStream != null)
{
try
{
defaultProperties.load(propertiesStream);
}
catch (IOException e)
{
logger.error("Could not read "+TRANSFORMERS_PROPERTIES+" so all properties will appear to be overridden by the customer", e);
}
}
else
{
logger.error("Could not find "+TRANSFORMERS_PROPERTIES+" so all properties will appear to be overridden by the customer");
}
return defaultProperties;
}
public Set<String> getPropertyNames()
{
Set<String> propertyNames = new HashSet<String>(subsystem.getPropertyNames());
for (String name: globalProperties.stringPropertyNames())
{
if (name.startsWith(TransformerConfig.PREFIX))
{
name = alias(name, OPEN_OFFICE, JOD_CONVERTER);
if (!propertyNames.contains(name))
{
propertyNames.add(name);
}
}
}
return propertyNames;
}
// When we moved the JodConverter into the Community edition (after 6.0.0-ea) we wanted to allow any Community
// settings for content.transformer.OpenOffice (and related pipeline transformers specified) in
// alfresco.global.properties to apply to the JodConverter (and related pipeline transformers), but where there
// is jodConverter that value should be used.
// content.transformer.JodConverter.
// content.transformer.JodConverter.Html2Pdf.
// content.transformer.JodConverter.2Pdf.
// content.transformer.complex.JodConverter.Image.
// content.transformer.complex.JodConverter.PdfBox
private String alias(String name, String from, String to)
{
int i = name.indexOf(from);
if (i != -1)
{
name = name.substring(0, i) + to + name.substring(i+from.length());
}
return name;
}
public void setProperties(Map<String, String> map)
{
subsystem.setProperties(map);
}
public void removeProperties(Collection<String> propertyNames)
{
subsystem.removeProperties(propertyNames);
}
}

View File

@@ -1,345 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import static org.alfresco.repo.content.transform.TransformerConfig.PREFIX;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import org.alfresco.service.cmr.repository.MimetypeService;
/**
* Provides access to a String representation of all transformer properties and values
* where these are sorted into groups.
*
* @author Alan Davis
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public class TransformerPropertyGetter
{
private final String string;
public TransformerPropertyGetter(boolean changesOnly, TransformerProperties transformerProperties,
MimetypeService mimetypeService, ContentTransformerRegistry transformerRegistry,
TransformerLog transformerLog, TransformerDebugLog transformerDebugLog)
{
List<ContentTransformer> availableTransformers = transformerRegistry.getTransformers();
StringBuilder sb = new StringBuilder();
// Log entries
appendLoggerSetting(sb, changesOnly, transformerLog, transformerDebugLog, transformerProperties);
// Miscellaneous
appendMiscellaneousSettings(sb, changesOnly, transformerProperties);
// Default transformer
Set<String> alreadySpecified = new HashSet<String>();
appendConfiguredTransformerSettings(sb, changesOnly, transformerProperties, mimetypeService, availableTransformers,
transformerRegistry, true, alreadySpecified,
"# Default transformer settings\n" +
"# ============================\n");
// Other transformers with configuration properties
appendConfiguredTransformerSettings(sb, changesOnly, transformerProperties, mimetypeService, availableTransformers,
transformerRegistry, false, alreadySpecified,
"# Transformers with configuration settings\n" +
"# ========================================\n" +
"# Commented out settings are hard coded values for information purposes\n");
// Other transformers without configuration properties
if (!changesOnly)
{
appendUnconfiguredTransformerSettings(sb, mimetypeService, alreadySpecified,
availableTransformers, transformerRegistry);
}
if (sb.length() == 0)
{
sb.append(changesOnly
? "No custom transformer properties defined"
: "No transformer properties defined");
}
string = sb.toString();
}
private void appendLoggerSetting(StringBuilder sb, boolean changesOnly, TransformerLog transformerLog,
TransformerDebugLog transformerDebugLog, TransformerProperties transformerProperties)
{
Properties defaultProperties = transformerProperties.getDefaultProperties();
String logEntries = transformerLog.getPropertyAndValue(defaultProperties);
String debugEntries = transformerDebugLog.getPropertyAndValue(defaultProperties);
boolean logEntriesChanged = !logEntries.startsWith("#");
boolean debugEntriesChanged = !debugEntries.startsWith("#");
if (!changesOnly || logEntriesChanged || debugEntriesChanged)
{
sb.append("# LOG and DEBUG history sizes\n");
sb.append("# ===========================\n");
sb.append("# Use small values as these logs are held in memory. 0 to disable.\n");
if (!changesOnly || logEntriesChanged)
{
sb.append(logEntries);
sb.append("\n");
}
if (!changesOnly || debugEntriesChanged)
{
sb.append(debugEntries);
sb.append("\n");
}
}
}
private void appendMiscellaneousSettings(StringBuilder sb, boolean changesOnly,
TransformerProperties transformerProperties)
{
Properties defaultProperties = transformerProperties.getDefaultProperties();
boolean first = true;
for (String propertyName: getMiscellaneousPropertyNames(defaultProperties))
{
String defaultValue = defaultProperties.getProperty(propertyName);
String value = transformerProperties.getProperty(propertyName);
boolean isDefaultValue = value == null || value.equals(defaultValue);
value = value == null ? defaultValue : value;
if (!changesOnly || !isDefaultValue)
{
if (first)
{
sb.append("\n");
sb.append("# Miscellaneous settings\n");
sb.append("# ======================\n");
first = false;
}
appendProperty(sb, propertyName, value, defaultValue);
sb.append("\n");
}
}
}
// Gets names from transformers.properties that are not log or content.transformer values.
private Set<String> getMiscellaneousPropertyNames(Properties defaultProperties)
{
Set<String> propertyNames = new TreeSet<String>();
for (Object key: defaultProperties.keySet())
{
String propertyName = key.toString();
if (!propertyName.startsWith(PREFIX) &&
!propertyName.equals(TransformerConfig.LOG_ENTRIES) &&
!propertyName.equals(TransformerConfig.DEBUG_ENTRIES))
{
propertyNames.add(propertyName);
}
}
return propertyNames;
}
public static void appendProperty(StringBuilder sb, String propertyName, String value, String defaultValue)
{
boolean isDefaultValue = value.equals(defaultValue);
if (isDefaultValue)
{
sb.append("# ");
}
sb.append(propertyName);
sb.append('=');
sb.append(value);
if (!isDefaultValue)
{
sb.append(" # default=");
sb.append(defaultValue);
}
}
private void appendConfiguredTransformerSettings(final StringBuilder sb, final boolean changesOnly,
TransformerProperties transformerProperties, MimetypeService mimetypeService,
final List<ContentTransformer> availableTransformers,
final ContentTransformerRegistry transformerRegistry,
final boolean defaultTransformer, final Set<String> alreadySpecified,
final String header)
{
final StringBuilder prefix = new StringBuilder();
final StringBuilder general = new StringBuilder();
final StringBuilder mimetypes = new StringBuilder();
final AtomicInteger start = new AtomicInteger(-1);
final AtomicReference<String> currentName = new AtomicReference<String>();
final Properties defaultProperties = transformerProperties.getDefaultProperties();
new TransformerPropertyNameExtractor()
{
/**
* Uses the propertyName and values rather than expanding the property name into multiple
* entries, in order to build up the string.
*/
@Override
protected void handleProperty(
String name,
String separator,
String firstExpression,
String secondExpression,
String suffix,
String use,
String value,
String propertyName,
Map<TransformerSourceTargetSuffixKey, TransformerSourceTargetSuffixValue> transformerSourceTargetSuffixValues, MimetypeService mimetypeService)
{
if (defaultTransformer == TransformerConfig.DEFAULT_TRANSFORMER.equals(name))
{
String defaultValue = defaultProperties == null ? null : defaultProperties.getProperty(propertyName);
boolean isDefaultValue = value.equals(defaultValue);
if (!changesOnly || !isDefaultValue)
{
String prevName = currentName.getAndSet(name);
if (prevName != null && !prevName.equals(name))
{
appendTransformerSettings(sb, start, prevName, prefix, general, mimetypes, mimetypeService,
alreadySpecified, availableTransformers, transformerRegistry, defaultTransformer, header);
}
StringBuilder tmp =
separator != null
? mimetypes
: TransformerConfig.PIPELINE.equals(suffix)
? prefix
: general;
if (isDefaultValue)
{
tmp.append("# ");
}
tmp.append(propertyName);
tmp.append('=');
tmp.append(value);
if (!isDefaultValue && defaultValue != null)
{
tmp.append(" # default=");
tmp.append(defaultValue);
}
tmp.append("\n");
}
}
}
}.getTransformerSourceTargetValues(TransformerConfig.ALL_SUFFIXES, true, true, transformerProperties, mimetypeService);
String currName = currentName.get();
if (currName != null)
{
if (defaultTransformer == TransformerConfig.DEFAULT_TRANSFORMER.equals(currName))
{
appendTransformerSettings(sb, start, currName, prefix, general, mimetypes, mimetypeService,
alreadySpecified, availableTransformers, transformerRegistry, defaultTransformer, header);
}
}
}
private void appendTransformerSettings(StringBuilder sb, AtomicInteger start, String transformerName, StringBuilder prefix,
StringBuilder general, StringBuilder mimetypes, MimetypeService mimetypeService, Set<String> alreadySpecified,
List<ContentTransformer> availableTransformers, ContentTransformerRegistry transformerRegistry,
boolean defaultTransformer, String header)
{
if (start.get() == -1)
{
if (sb.length() != 0)
{
sb.append('\n');
}
sb.append(header);
start.set(sb.length());
}
if (!defaultTransformer)
{
alreadySpecified.add(transformerName);
ContentTransformer transformer;
prefix.insert(0, '\n');
try
{
transformer = transformerRegistry.getTransformer(transformerName);
boolean available = availableTransformers.contains(transformer);
prefix.insert(1, transformer.getComments(available));
}
catch (IllegalArgumentException e)
{
if (transformerName.startsWith(TransformerConfig.TRANSFORMER))
{
transformerName = transformerName.substring(TransformerConfig.TRANSFORMER.length());
}
prefix.insert(1, ContentTransformerHelper.getCommentName(transformerName)+"# Unregistered transformer\n");
transformer = null;
}
sb.append(prefix.toString());
}
sb.append(general.toString());
sb.append(mimetypes.toString());
// Reset for next one
prefix.setLength(0);
general.setLength(0);
mimetypes.setLength(0);
}
private void appendUnconfiguredTransformerSettings(StringBuilder sb, MimetypeService mimetypeService,
Set<String> alreadySpecified, List<ContentTransformer> availableTransformers,
ContentTransformerRegistry transformerRegistry)
{
boolean first = true;
for (ContentTransformer transformer: transformerRegistry.getAllTransformers())
{
String name = transformer.getName();
if (!alreadySpecified.contains(name))
{
if (first)
{
sb.append("\n");
sb.append("# Transformers without extra configuration settings\n");
sb.append("# =================================================\n\n");
first = false;
}
else
{
sb.append('\n');
}
boolean available = availableTransformers.contains(transformer);
sb.append(transformer.getComments(available));
}
}
}
public String toString()
{
return string;
}
}

View File

@@ -1,528 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
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.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.alfresco.service.cmr.repository.MimetypeService;
/**
* Provides access to transformer property names and values.
*
* @author Alan Davis
*
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public abstract class TransformerPropertyNameExtractor
{
private static Pattern EXTENSIONS_SEPARATOR = Pattern.compile("[^]\\\\]\\.");
private static String[] NO_EXT_MATCH = new String[0];
/**
* Returns a set of transformer name, source extension, target extension and value
* from property names that defined transformation limits. When the separator indicates
* it is followed by a regular expression that matches multiple mimetypes, more than one
* value may be added. When there is a value defined for specific extensions it wins over
* any regular expression value.
* @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 includeUse if true, additionally checks for specific usage values that override
* the normal defaults. Such properties have a suffix of ".use.<use>" where <use>
* is a value such as "index", "webpreview", "doclib", "syncRule", "aysncRule".
* @param transformerProperties that provides the properties
* @param mimetypeService MimetypeService
*/
protected Collection<TransformerSourceTargetSuffixValue> getTransformerSourceTargetValues(Collection<String> suffixes,
boolean includeSummary, boolean includeUse, TransformerProperties transformerProperties, MimetypeService mimetypeService)
{
return new ArrayList<TransformerSourceTargetSuffixValue>(
getTransformerSourceTargetValuesMap(suffixes, includeSummary, true, includeUse, transformerProperties, mimetypeService).values());
}
/**
* Returns a map to access transformer name, source extension and target extension to
* transformer name, source extension, target extension and value, created from property
* names that defined transformation limits. When the separator indicates
* it is followed by a regular expression that matches multiple mimetypes, more than one
* value may be added. When there is a value defined for specific extensions it wins over
* any regular expression value.
* @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 include property names without the separator to
* source mimetype and target mimetype.
* @param includeExtensions if false will exclude property names with the separator to
* source mimetype and target mimetype.
* @param includeUse if true, additionally checks for specific usage values that override
* the normal defaults. Such properties have a suffix of ".use.<use>" where <use>
* is a value such as "index", "webpreview", "doclib", "syncRule", "aysncRule".
* @param transformerProperties that provides the properties
* @param mimetypeService MimetypeService
*/
protected Map<TransformerSourceTargetSuffixKey, TransformerSourceTargetSuffixValue> getTransformerSourceTargetValuesMap(Collection<String> suffixes,
boolean includeSummary, boolean includeExtensions, boolean includeUse, TransformerProperties transformerProperties, MimetypeService mimetypeService)
{
Map<TransformerSourceTargetSuffixKey, TransformerSourceTargetSuffixValue> transformerSourceTargetSuffixValues =
new LinkedHashMap<TransformerSourceTargetSuffixKey, TransformerSourceTargetSuffixValue>();
List<String> propertyNames = new ArrayList<String>(transformerProperties.getPropertyNames());
Collections.sort(propertyNames);
for (String propertyName: propertyNames)
{
if (propertyName.startsWith(PREFIX))
{
String use = null;
String propertyNameWithoutUse = propertyName;
if (includeUse)
{
int i = propertyName.lastIndexOf(TransformerConfig.USE);
if (i != -1)
{
int j = i+TransformerConfig.USE.length();
if (propertyName.length()-j > 0)
{
use = propertyName.substring(j);
propertyNameWithoutUse = propertyName.substring(0, i);
}
}
}
suffixesLoop:
for (String suffix: suffixes)
{
if (propertyNameWithoutUse.endsWith(suffix))
{
String value = transformerProperties.getProperty(propertyName);
String transformerName = propertyNameWithoutUse.substring(CONTENT.length(), propertyNameWithoutUse.length()-suffix.length());
boolean separatorMatch = false;
for (String separator: TransformerConfig.SEPARATORS)
{
int i = transformerName.lastIndexOf(separator);
if (i != -1)
{
separatorMatch = true;
if (includeExtensions)
{
String extensions = transformerName.substring(i+separator.length());
String[] ext = splitExt(extensions);
if (ext.length == 2)
{
transformerName = transformerName.substring(0, i);
String firstExpression = ext[0];
String secondExpression = ext[1];
handleProperty(transformerName,
separator, firstExpression, secondExpression,
suffix, use, value, propertyName, transformerSourceTargetSuffixValues, mimetypeService);
break suffixesLoop;
}
}
}
}
if (!separatorMatch && includeSummary)
{
handleProperty(transformerName, null, null, null, suffix, use, value, propertyName, transformerSourceTargetSuffixValues, mimetypeService);
break suffixesLoop;
}
}
}
}
}
return transformerSourceTargetSuffixValues;
}
/**
* Handles a property to add values to the supplied transformerSourceTargetSuffixValues.
* If the separator is null, this indicates that the property provides a transformer
* wide value, so firstExpression and secondExpression should also be ignored.
*/
protected void handleProperty(String transformerName, String separator,
String firstExpression, String secondExpression, String suffix, String use, String value,
String propertyName,
Map<TransformerSourceTargetSuffixKey, TransformerSourceTargetSuffixValue> transformerSourceTargetSuffixValues, MimetypeService mimetypeService)
{
if (separator == null)
{
addTransformerSourceTargetValue(transformerSourceTargetSuffixValues,
false,
transformerName, ANY, ANY, suffix,
use, value, mimetypeService);
}
else
{
List<String> sourceExtensions = (TransformerConfig.EXTENSIONS.equals(separator))
? getMatchingExtensionsFromExtensions(firstExpression, mimetypeService)
: getMatchingExtensionsFromMimetypes( firstExpression, mimetypeService);
List<String> targetExtensions = (TransformerConfig.EXTENSIONS.equals(separator))
? getMatchingExtensionsFromExtensions(secondExpression, mimetypeService)
: getMatchingExtensionsFromMimetypes( secondExpression, mimetypeService);
for (String sourceExt : sourceExtensions)
{
for (String targetExt : targetExtensions)
{
addTransformerSourceTargetValue(transformerSourceTargetSuffixValues,
(TransformerConfig.MIMETYPES.equals(separator)),
transformerName, sourceExt, targetExt, suffix,
use, value, mimetypeService);
}
}
}
}
/**
* Optionally adds a new TransformerSourceTargetValue and discards some when
* there is another 'better' property.<p>
*
* If there is a property for the max value and another for the limit the lower
* one wins. If equal, the max value wins.<p>
*
* If the supplied value is constructed from a mimetypes value it wins over one
* constructed from an extensions property.
*/
private void addTransformerSourceTargetValue(
Map<TransformerSourceTargetSuffixKey, TransformerSourceTargetSuffixValue> transformerSourceTargetSuffixValues,
boolean mimetypeProperty, String transformerName, String sourceExt, String targetExt, String suffix,
String use, String value, MimetypeService mimetypeService)
{
TransformerSourceTargetSuffixValue transformerSourceTargetSuffixValue =
new TransformerSourceTargetSuffixValue(transformerName, sourceExt, targetExt, suffix, use, value, mimetypeService);
TransformerSourceTargetSuffixKey key = transformerSourceTargetSuffixValue.key();
if (mimetypeProperty || !transformerSourceTargetSuffixValues.containsKey(key))
{
TransformerSourceTargetSuffixKey siblingKey = transformerSourceTargetSuffixValue.getSiblingKey();
TransformerSourceTargetSuffixValue sibling = transformerSourceTargetSuffixValues.get(siblingKey);
boolean doAdd = true;
if (sibling != null)
{
doAdd = false;
long newValue = Long.parseLong(value);
if (newValue > 0)
{
long oldValue = Long.parseLong(sibling.value);
// If max rather than limit value
boolean isMax =
suffix == TransformerConfig.MAX_SOURCE_SIZE_K_BYTES ||
suffix == TransformerConfig.TIMEOUT_MS ||
suffix == TransformerConfig.MAX_PAGES;
if (oldValue < 0 || (isMax && oldValue >= newValue) || (!isMax && oldValue > newValue))
{
transformerSourceTargetSuffixValues.remove(siblingKey);
doAdd = true;
}
}
}
if (doAdd)
{
transformerSourceTargetSuffixValues.put(key, transformerSourceTargetSuffixValue);
}
}
}
/**
* Splits the extensions into two parts. It does this by looking for a '.'
* that is not escaped (preceded by a back slash '\').
* This is to allow regular expressions to be used for mimetypes.
*/
String[] splitExt(String extensions)
{
String[] ext = NO_EXT_MATCH;
Matcher matcher = EXTENSIONS_SEPARATOR.matcher(extensions);
if (matcher.find())
{
int i = matcher.start();
ext = new String[2];
ext[0] = extensions.substring(0, i+1).replaceAll("\\\\\\.", ".");
ext[1] = extensions.substring(i+2).replaceAll("\\\\\\.", ".");
}
return ext;
}
/**
* Returns a regex Pattern for the supplied expression where '*' represents zero
* or more characters.
*/
Pattern pattern(String expression)
{
// Turn the pattern into a regular expression where any special regex
// characters have no meaning and then get any * values to represent
// zero or more chars.
String regex = Pattern.quote(expression).replaceAll("\\*", "\\\\E.*\\\\Q");
return Pattern.compile(regex);
}
/**
* Gets the extensions of the mimetypes that match the given expression.
* However if the expression is "*", only the ANY ("*") extension is returned.
* @param expression which may contain '*' to represent zero or more characters.
* @param mimetypeService MimetypeService
* @return the list of extensions of mimetypes that match
*/
List<String> getMatchingExtensionsFromMimetypes(
String expression, MimetypeService mimetypeService)
{
if (ANY.equals(expression))
{
return Collections.singletonList(ANY);
}
Pattern pattern = pattern(expression);
List<String> matchingMimetypes = new ArrayList<String>(1);
for (String mimetype : mimetypeService.getMimetypes())
{
if (pattern.matcher(mimetype).matches())
{
String ext = mimetypeService.getExtension(mimetype);
matchingMimetypes.add(ext);
}
}
return matchingMimetypes;
}
/**
* Gets the extensions that match the given expression. Only the main extension
* of each mimetype is checked.
* However if the expression is "*", only the ANY ("*") extension is returned.
* @param expression which may contain '*' to represent zero or more characters.
* @param mimetypeService MimetypeService
* @return the list of extensions that match
*/
List<String> getMatchingExtensionsFromExtensions(
String expression, MimetypeService mimetypeService)
{
if (ANY.equals(expression))
{
return Collections.singletonList(ANY);
}
Pattern pattern = pattern(expression);
List<String> matchingMimetypes = new ArrayList<String>(1);
for (String mimetype : mimetypeService.getMimetypes())
{
String ext = mimetypeService.getExtension(mimetype);
if (pattern.matcher(ext).matches())
{
matchingMimetypes.add(ext);
}
}
return matchingMimetypes;
}
/**
* Returns a transformer property value if it exists from the supplied map.
* @param transformerName of the transformer
* @param sourceExt {@code null} indicates this is a transformer wide property.
* @param targetExt String
* @param suffix String
* @param use String
* @param transformerSourceTargetSuffixValues map of values
* @return the value or {@code null} if not set.
*/
protected String getProperty(String transformerName, String sourceExt, String targetExt,
String suffix, String use, Map<TransformerSourceTargetSuffixKey, TransformerSourceTargetSuffixValue> transformerSourceTargetSuffixValues)
{
TransformerSourceTargetSuffixKey key = new TransformerSourceTargetSuffixKey(transformerName,
(sourceExt == null ? ANY : sourceExt), (targetExt == null ? ANY : targetExt), suffix, use);
TransformerSourceTargetSuffixValue value = transformerSourceTargetSuffixValues.get(key);
return value == null ? null : value.value;
}
}
class TransformerSourceTargetSuffixKey
{
final String transformerName;
final String sourceExt;
final String targetExt;
final String suffix;
final String use;
// sourceExt and targetExt should never be null, but be set to ANY
public TransformerSourceTargetSuffixKey(String transformerName, String sourceExt, String targetExt, String suffix, String use)
{
this.transformerName = transformerName;
this.sourceExt = sourceExt;
this.targetExt = targetExt;
this.suffix = suffix;
this.use = use;
}
public String toString()
{
return transformerName+(sourceExt.equals(ANY) && targetExt.equals(ANY)
? ""
: TransformerConfig.EXTENSIONS+sourceExt+'.'+targetExt)+
suffix+
(use == null || ANY.equals(use) ? "" : TransformerConfig.USE + use);
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((sourceExt == null) ? 0 : sourceExt.hashCode());
result = prime * result + ((suffix == null) ? 0 : suffix.hashCode());
result = prime * result + ((targetExt == null) ? 0 : targetExt.hashCode());
result = prime * result + ((transformerName == null) ? 0 : transformerName.hashCode());
result = prime * result + ((use == null) ? 0 : use.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
TransformerSourceTargetSuffixKey other = (TransformerSourceTargetSuffixKey) obj;
if (sourceExt == null)
{
if (other.sourceExt != null)
return false;
}
else if (!sourceExt.equals(other.sourceExt))
return false;
if (suffix == null)
{
if (other.suffix != null)
return false;
}
else if (!suffix.equals(other.suffix))
return false;
if (targetExt == null)
{
if (other.targetExt != null)
return false;
}
else if (!targetExt.equals(other.targetExt))
return false;
if (transformerName == null)
{
if (other.transformerName != null)
return false;
}
else if (!transformerName.equals(other.transformerName))
return false;
if (use == null)
{
if (other.use != null)
return false;
}
else if (!use.equals(other.use))
return false;
return true;
}
}
class TransformerSourceTargetSuffixValue extends TransformerSourceTargetSuffixKey
{
final String value;
final String sourceMimetype;
final String targetMimetype;
// sourceExt and targetExt should never be null, but be set to ANY
public TransformerSourceTargetSuffixValue(String transformerName, String sourceExt,
String targetExt, String suffix, String use, String value, MimetypeService mimetypeService)
{
super(transformerName, sourceExt, targetExt, suffix, use);
this.value = value;
this.sourceMimetype = ANY.equals(sourceExt) ? ANY : mimetypeService.getMimetype(sourceExt);
this.targetMimetype = ANY.equals(targetExt) ? ANY : mimetypeService.getMimetype(targetExt);
}
public TransformerSourceTargetSuffixKey key()
{
return new TransformerSourceTargetSuffixKey(transformerName, sourceExt, targetExt, suffix, use);
}
/**
* @return the key of the sibling property for the max value if this is the limit value and one
* for the limit value if the max value.
*/
public TransformerSourceTargetSuffixKey getSiblingKey()
{
String siblingSuffix =
suffix == TransformerConfig.MAX_SOURCE_SIZE_K_BYTES
? TransformerConfig.READ_LIMIT_K_BYTES
: suffix == TransformerConfig.READ_LIMIT_K_BYTES
? TransformerConfig.MAX_SOURCE_SIZE_K_BYTES
: suffix == TransformerConfig.TIMEOUT_MS
? TransformerConfig.READ_LIMIT_TIME_MS
: suffix == TransformerConfig.READ_LIMIT_TIME_MS
? TransformerConfig.TIMEOUT_MS
: suffix == TransformerConfig.MAX_PAGES
? TransformerConfig.PAGE_LIMIT
: TransformerConfig.MAX_PAGES;
return new TransformerSourceTargetSuffixKey(transformerName, sourceExt, targetExt, siblingSuffix, use);
}
public String toString()
{
return super.toString()+'='+value;
}
@Override
public int hashCode()
{
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((value == null) ? 0 : value.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (!super.equals(obj))
return false;
TransformerSourceTargetSuffixValue other = (TransformerSourceTargetSuffixValue) obj;
if (!value.equals(other.value))
return false;
return true;
}
}

View File

@@ -1,619 +0,0 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* 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 <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.repo.content.transform;
import static org.alfresco.repo.content.transform.TransformerConfig.ANY;
import static org.alfresco.repo.content.transform.TransformerConfig.AVAILABLE;
import static org.alfresco.repo.content.transform.TransformerConfig.CONTENT;
import static org.alfresco.repo.content.transform.TransformerConfig.ERROR_TIME;
import static org.alfresco.repo.content.transform.TransformerConfig.FAILOVER;
import static org.alfresco.repo.content.transform.TransformerConfig.INITIAL_COUNT;
import static org.alfresco.repo.content.transform.TransformerConfig.INITIAL_TIME;
import static org.alfresco.repo.content.transform.TransformerConfig.MAX_PAGES;
import static org.alfresco.repo.content.transform.TransformerConfig.MAX_SOURCE_SIZE_K_BYTES;
import static org.alfresco.repo.content.transform.TransformerConfig.PAGE_LIMIT;
import static org.alfresco.repo.content.transform.TransformerConfig.PIPELINE;
import static org.alfresco.repo.content.transform.TransformerConfig.PRIORITY;
import static org.alfresco.repo.content.transform.TransformerConfig.BLACKLIST;
import static org.alfresco.repo.content.transform.TransformerConfig.READ_LIMIT_K_BYTES;
import static org.alfresco.repo.content.transform.TransformerConfig.READ_LIMIT_TIME_MS;
import static org.alfresco.repo.content.transform.TransformerConfig.SUPPORTED;
import static org.alfresco.repo.content.transform.TransformerConfig.THRESHOLD_COUNT;
import static org.alfresco.repo.content.transform.TransformerConfig.TIMEOUT_MS;
import static org.alfresco.repo.content.transform.TransformerConfig.TRANSFORMER;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.alfresco.service.cmr.repository.MimetypeService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.util.Pair;
/**
* Provides methods to set and remove transformer properties and values.
*
* @author Alan Davis
* @deprecated The transformations code is being moved out of the codebase and replaced by the new async RenditionService2 or other external libraries.
*/
@Deprecated
public class TransformerPropertySetter
{
/**
* Matches lines
*/
private static final Pattern LINE_SPLIT = Pattern.compile("^(.*)$", Pattern.MULTILINE);
/**
* Matches leading white space and trailing comments
*/
private static final Pattern COMMENT = Pattern.compile("(^\\s+)|(\\s*#.*)|(\\s+$)");
/**
* Tries to match a space that should be a newline. JConsole has turned \n into spaces!
*/
private static Pattern NEWLINE_CORRECTION = Pattern.compile("([^#]\\s*) ((content\\.transformer\\.)|(transformer\\.))");
/**
* Integer Value
*/
private static final Pattern INTEGER = Pattern.compile("^-?\\d+$");
private final TransformerProperties transformerProperties;
private final MimetypeService mimetypeService;
private final ContentTransformerRegistry transformerRegistry;
public TransformerPropertySetter(TransformerProperties transformerProperties, MimetypeService mimetypeService,
ContentTransformerRegistry transformerRegistry)
{
this.transformerProperties = transformerProperties;
this.mimetypeService = mimetypeService;
this.transformerRegistry = transformerRegistry;
}
/**
* Sets transformer properties from the supplied multi line propertyNamesAndValues.
* @throws IllegalArgumentException if an unexpected line is found
*/
public int setProperties(String propertyNamesAndValues)
{
Map<String, String> map = new HashMap<String, String>();
Map<String, String> transformerReferences = new HashMap<String, String>();
Set<String> dynamicTransformerNames = new HashSet<String>();
for (String propertyNameAndValue: extractProperties(propertyNamesAndValues, true, transformerReferences, dynamicTransformerNames))
{
Pair<String, String> pair = splitNameAndValue(propertyNameAndValue);
String propertyName = pair.getFirst();
String value = pair.getSecond();
if (map.containsKey(propertyName))
{
throw new IllegalArgumentException(propertyName+" has been specified more than once");
}
if (!value.equals(transformerProperties.getProperty(propertyName)))
{
map.put(propertyName, value);
}
}
// Check transformer names exist or will exist
checkTransformerReferences(transformerReferences, dynamicTransformerNames);
int size = map.size();
if (size > 0)
{
transformerProperties.setProperties(map);
}
return size;
}
private void checkTransformerReferences(Map<String, String> transformerReferences,
Set<String> dynamicTransformerNames) throws IllegalArgumentException
{
// Add on the static transformer names into the dynamic transformer names supplied
Set<String> allTransformerNames = new HashSet<String>(dynamicTransformerNames);
for (ContentTransformer transformer: transformerRegistry.getAllTransformers())
{
String name = transformer.getName();
allTransformerNames.add(name);
}
allTransformerNames.add(TransformerConfig.DEFAULT_TRANSFORMER);
for (String transformerSimpleName: transformerReferences.keySet())
{
if (!ANY.equals(transformerSimpleName))
{
String name = TRANSFORMER+transformerSimpleName;
if (!allTransformerNames.contains(name))
{
String line = transformerReferences.get(transformerSimpleName);
throw unexpectedProperty("Transformer "+transformerSimpleName+" does not exist", line);
}
}
}
}
/**
* Removes transformer properties from the supplied multi line propertyNames.
* @param propertyNames which optionally include a value
* @throws IllegalArgumentException if an unexpected line is found
*/
public int removeProperties(String propertyNames)
{
Set<String> remove = new HashSet<String>();
Map<String, String> transformerReferences = new HashMap<String, String>();
Set<String> dynamicTransformerNames = new HashSet<String>();
Properties defaultProperties = transformerProperties.getDefaultProperties();
for (String propertyNameAndValue: extractProperties(propertyNames, false, transformerReferences, dynamicTransformerNames))
{
Pair<String, String> pair = splitNameAndValue(propertyNameAndValue);
String propertyName = pair.getFirst();
if (transformerProperties.getProperty(propertyName) == null)
{
throw unexpectedProperty("Does not exist", propertyName);
}
if (defaultProperties.getProperty(propertyName) != null)
{
throw unexpectedProperty("Is a deafult property so may not be removed", propertyName);
}
remove.add(propertyName);
}
transformerProperties.removeProperties(remove);
return remove.size();
}
/**
* Returns an array of transformer property names (and optional values).
* @param text to be parsed
* @param hasValue values are required, optionally exist when false.
* @param transformerReferences map of transformerReferences to a line that referenced them.
* @param dynamicTransformerNames added via properties
* @return a list of cleaned up transformer properties from the text
* @throws IllegalArgumentException if an unexpected line is found
*/
private List<String> extractProperties(String text, boolean hasValue, Map<String,
String> transformerReferences, Set<String> dynamicTransformerNames)
{
List<String> properties = new ArrayList<String>();
text = fixJConsolesMissingNewlines(text);
// Split the lines
Matcher lineMatcher = LINE_SPLIT.matcher(text);
while (lineMatcher.find())
{
String line = lineMatcher.group();
// Strip comments from lines
Matcher commentMatcher = COMMENT.matcher(line);
line = commentMatcher.replaceAll("");
// Ignore blank lines
if (line.length() != 0)
{
String lowerLine = line.toLowerCase(); // Should we set the lower case value anyway
if (lowerLine.startsWith(TransformerConfig.PREFIX))
{
checkTransformerProperty(hasValue, line, transformerReferences, dynamicTransformerNames);
properties.add(line);
}
else if (lowerLine.startsWith(TransformerConfig.DEBUG_ENTRIES))
{
checkInteger(hasValue, line, TransformerConfig.DEBUG_ENTRIES.length());
properties.add(line);
}
else if (lowerLine.startsWith(TransformerConfig.LOG_ENTRIES))
{
checkInteger(hasValue, line, TransformerConfig.LOG_ENTRIES.length());
properties.add(line);
}
else if (lowerLine.startsWith(TransformerConfig.STRICT_MIMETYPE_CHECK_WHITELIST_MIMETYPES))
{
checkMimetypeList(hasValue, line, TransformerConfig.STRICT_MIMETYPE_CHECK_WHITELIST_MIMETYPES.length(), true);
properties.add(line);
}
else
{
throw unexpectedProperty("Not a transformer property", line);
}
}
}
return properties;
}
/**
* Multi-line Strings from JConsole have their end of line bytes replaced by a
* single space. The following method tries to put them back in.<p>
*
* It tries to avoid commented out transformers.
*
* @param text to scan
* @return modified text
*/
String fixJConsolesMissingNewlines(String text)
{
Matcher newlineMatcher = NEWLINE_CORRECTION.matcher(text);
text = newlineMatcher.replaceAll("$1\n$2");
return text;
}
private void checkTransformerProperty(boolean hasValue, String line,
Map<String, String> transformerReferences, Set<String> dynamicTransformerNames)
{
int j = line.indexOf('=');
String propertyName = j != -1 ? line.substring(0, j) : line;
TransformerPropertyNameExtractor extractor = new TransformerPropertyNameExtractor() {};
boolean validPropertyName = false;
String transformerName = null;
String suffix = null;
String separator = null;
int k = propertyName.lastIndexOf(TransformerConfig.USE);
if (k != -1)
{
int l = k+TransformerConfig.USE.length();
if (propertyName.length()-l > 0)
{
propertyName = propertyName.substring(0, k);
}
else
{
throw unexpectedProperty("Missing use value after ...use. ", line);
}
}
suffixesLoop:
for (String aSuffix: TransformerConfig.ALL_SUFFIXES)
{
if (propertyName.endsWith(aSuffix))
{
transformerName = propertyName.substring(CONTENT.length(), propertyName.length()-aSuffix.length());
suffix = aSuffix;
boolean separatorMatch = false;
for (String aSeparator: TransformerConfig.SEPARATORS)
{
int i = transformerName.lastIndexOf(aSeparator);
if (i != -1)
{
separatorMatch = true;
String extensions = transformerName.substring(i+aSeparator.length());
String[] ext = extractor.splitExt(extensions);
if (ext.length == 2)
{
String firstExpression = ext[0];
String secondExpression = ext[1];
if (aSeparator == TransformerConfig.EXTENSIONS)
{
if (extractor.getMatchingExtensionsFromExtensions(firstExpression, mimetypeService).size() == 0)
{
throw unexpectedProperty("Invalid source extension "+firstExpression, line);
}
if (extractor.getMatchingExtensionsFromExtensions(secondExpression, mimetypeService).size() == 0)
{
throw unexpectedProperty("Invalid target extension "+secondExpression, line);
}
}
else // if (separator == TransformerConfig.MIMETYPES)
{
if (extractor.getMatchingExtensionsFromMimetypes(firstExpression, mimetypeService).size() == 0)
{
throw unexpectedProperty("Invalid source mimetype "+firstExpression, line);
}
if (extractor.getMatchingExtensionsFromMimetypes(secondExpression, mimetypeService).size() == 0)
{
throw unexpectedProperty("Invalid target mimetype "+secondExpression, line);
}
}
transformerName = transformerName.substring(0, i);
separator = aSeparator;
validPropertyName = true;
break suffixesLoop;
}
}
}
separator = null;
if (!separatorMatch)
{
validPropertyName = true;
break suffixesLoop;
}
}
}
if (!validPropertyName)
{
throw unexpectedProperty("Possible typo in the property name", line);
}
checkTransformerPropertyValue(hasValue, line, j, transformerName, separator, suffix,
transformerReferences, dynamicTransformerNames);
}
private void checkTransformerPropertyValue(boolean hasValue, String line, int i,
String transformerName, String separator, String suffix,
Map<String, String> transformerReferences, Set<String> dynamicTransformerNames)
{
if (MAX_SOURCE_SIZE_K_BYTES.equals(suffix) ||
TIMEOUT_MS.equals(suffix) ||
READ_LIMIT_K_BYTES.equals(suffix) ||
READ_LIMIT_TIME_MS.equals(suffix) ||
INITIAL_COUNT.equals(suffix) ||
INITIAL_TIME.equals(suffix) ||
ERROR_TIME.equals(suffix))
{
checkLong(hasValue, line, i);
}
else if (MAX_PAGES.equals(suffix) ||
PAGE_LIMIT.equals(suffix) ||
THRESHOLD_COUNT.equals(suffix) ||
PRIORITY.equals(suffix))
{
checkInteger(hasValue, line, i);
}
else if (SUPPORTED.equals(suffix) ||
AVAILABLE.equals(suffix))
{
checkBoolean(hasValue, line, i);
}
else if (PIPELINE.equals(suffix) ||
FAILOVER.equals(suffix))
{
dynamicTransformerNames.add(transformerName);
if (separator != null)
{
throw unexpectedProperty("Separator was not expected", line);
}
if (PIPELINE.equals(suffix))
{
checkPipelineValue(hasValue, line, i, transformerReferences);
}
else
{
checkFailoverValue(hasValue, line, i, transformerReferences);
}
}
else if (BLACKLIST.equals(suffix))
{
checkNodeRefList(hasValue, line, i);
}
}
private void checkInteger(boolean hasValue, String line, int i)
{
String value = checkValue(hasValue, line, i);
if (value != null)
{
if (!INTEGER.matcher(value).find())
{
throw unexpectedProperty("Expected an integer value", line);
}
try
{
Integer.parseInt(value);
}
catch (NumberFormatException e)
{
throw unexpectedProperty("Expected an int value", line);
}
}
}
private void checkLong(boolean hasValue, String line, int i)
{
String value = checkValue(hasValue, line, i);
if (value != null)
{
if (!INTEGER.matcher(value).find())
{
throw unexpectedProperty("Expected an integer value", line);
}
try
{
Long.parseLong(value);
}
catch (NumberFormatException e)
{
throw unexpectedProperty("Expected a long value", line);
}
}
}
private void checkBoolean(boolean hasValue, String line, int i)
{
String value = checkValue(hasValue, line, i);
if (value != null)
{
if (!value.equalsIgnoreCase("true") &&
!value.equalsIgnoreCase("false"))
{
throw unexpectedProperty("Expected true or false value", line);
}
}
}
private void checkPipelineValue(boolean hasValue, String line, int i,
Map<String, String> transformerReferences)
{
String value = checkValue(hasValue, line, i);
if (value != null)
{
String[] transformerNamesAndExtensions = value.split("\\|");
int count = transformerNamesAndExtensions.length;
// Must be an even number of | characters, as they should be
// an initial transformer and then pairs of extension and transformer.
if (count < 2 || count % 2 == 0)
{
throw unexpectedProperty("Incomplete pipeline value", line);
}
for (int j=0; j < count; j++)
{
if (j % 2 == 0)
{
// Added reference to the transformer if not ANY transformer
if (transformerNamesAndExtensions[j].length() > 0)
{
transformerReferences.put(transformerNamesAndExtensions[j], line);
}
}
else
{
String extension = transformerNamesAndExtensions[j];
TransformerPropertyNameExtractor extractor= new TransformerPropertyNameExtractor() {};
if (extractor.getMatchingExtensionsFromExtensions(extension, mimetypeService).size() == 0)
{
throw unexpectedProperty("Invalid intermediate extension "+extension, line);
}
}
}
}
}
private void checkFailoverValue(boolean hasValue, String line, int i,
Map<String, String> transformerReferences)
{
String value = checkValue(hasValue, line, i);
if (value != null)
{
String[] transformerNames = value.split("\\|");
int count = transformerNames.length;
// Should be more than one transformer
if (count < 2)
{
throw unexpectedProperty("Can't failover if there is only on transformer", line);
}
// Add every component
for (int j=0; j < count; j++)
{
if (transformerNames[j].length() > 0)
{
transformerReferences.put(transformerNames[j], line);
}
}
}
}
private void checkNodeRefList(boolean hasValue, String line, int i)
{
String value = checkValue(hasValue, line, i);
if (value != null)
{
for (String nodeRefString: line.split(", *"))
{
nodeRefString = nodeRefString.trim();
if (nodeRefString.length() != 0 && !NodeRef.isNodeRef(nodeRefString))
{
throw unexpectedProperty("Expected NodeRef value "+nodeRefString, line);
}
}
}
}
private void checkMimetypeList(boolean hasValue, String line, int i, boolean evenNumberOfEntries)
{
String value = checkValue(hasValue, line, i);
value = value == null ? "" : value.trim();
if (value.length() > 0)
{
String[] mimetypes = value.split(";");
if (evenNumberOfEntries && mimetypes.length % 2 != 0)
{
throw unexpectedProperty("There should be an even number of mimetypes.", line);
}
else
{
// Check the dericed mimetype on the Node are valid. Tika may have mimetypes we know nothing about.
List<String> knownMimetypes = mimetypeService.getMimetypes();
for (int j=0; j<mimetypes.length; j+=2)
{
String dervivedMimetype = mimetypes[j];
dervivedMimetype = dervivedMimetype.trim();
if (!knownMimetypes.contains(dervivedMimetype))
{
throw unexpectedProperty("Unregistered mimetype: "+dervivedMimetype, line);
}
}
}
}
}
/**
* Check that a line has an assignment of a value if hasValue is true and
* if false the assignment is optional.
* @param hasValue
* @param line
* @param i the offset where the assignment should start
* @return the value if there is an assignment. null otherwise.
* @throws IllegalArgumentException if there is a problem.
*/
private String checkValue(boolean hasValue, String line, int i)
{
int l = line.length();
if (( hasValue && (i == -1 || l <= i || line.charAt(i) != '=')) ||
(!hasValue && ( l < i || (i != -1 && l > i && line.charAt(i) != '='))))
{
throw unexpectedProperty("Expected a value after an '=' at char "+i, line);
}
return (hasValue || (i != -1 && l > i)) ? line.substring(i+1) : null;
}
private IllegalArgumentException unexpectedProperty(String context, String line) throws IllegalArgumentException
{
return new IllegalArgumentException("Unexpected property: "+line+" "+context);
}
Pair<String, String> splitNameAndValue(String propertyNameAndValue)
{
int i = propertyNameAndValue.indexOf('=');
String name = i != -1 ? propertyNameAndValue.substring(0, i) : propertyNameAndValue;
String value = i != -1 ? propertyNameAndValue.substring(i+1) : "";
Pair<String, String> pair = new Pair<String, String>(name, value);
return pair;
}
}

Some files were not shown because too many files have changed in this diff Show More