diff --git a/l10n.properties b/l10n.properties index 26efac3f76..fe5e58be8e 100644 --- a/l10n.properties +++ b/l10n.properties @@ -3,5 +3,5 @@ MESSAGE_SEARCH_PATH="src/main/resources/alfresco/messages/action-config*.properties src/main/resources/alfresco/messages/action-service*.properties src/main/resources/alfresco/messages/activiti-engine-messages*.properties src/main/resources/alfresco/messages/activities-service*.properties src/main/resources/alfresco/messages/activity-list*.properties src/main/resources/alfresco/messages/application-model*.properties src/main/resources/alfresco/messages/authentication*.properties src/main/resources/alfresco/messages/bootstrap-content-template-examples*.properties src/main/resources/alfresco/messages/bootstrap-example-javascripts*.properties src/main/resources/alfresco/messages/bootstrap-example-smartfoldertemplates*.properties src/main/resources/alfresco/messages/bootstrap-imapScripts*.properties src/main/resources/alfresco/messages/bootstrap-javascripts*.properties src/main/resources/alfresco/messages/bootstrap-messages*.properties src/main/resources/alfresco/messages/bootstrap-readme-template*.properties src/main/resources/alfresco/messages/bootstrap-spaces*.properties src/main/resources/alfresco/messages/bootstrap-templates*.properties src/main/resources/alfresco/messages/bootstrap-tutorial*.properties src/main/resources/alfresco/messages/bootstrap-webScripts*.properties src/main/resources/alfresco/messages/bootstrap-webScriptsExtensions*.properties src/main/resources/alfresco/messages/bpm-messages*.properties src/main/resources/alfresco/messages/categories*.properties src/main/resources/alfresco/messages/coci-service*.properties src/main/resources/alfresco/messages/content-filter-languages*.properties src/main/resources/alfresco/messages/content-model*.properties src/main/resources/alfresco/messages/copy-service*.properties src/main/resources/alfresco/messages/custommodel-service*.properties src/main/resources/alfresco/messages/discussion-messages*.properties src/main/resources/alfresco/messages/distributionpolicies-model*.properties src/main/resources/alfresco/messages/doclink-service*.properties src/main/resources/alfresco/messages/download-model*.properties src/main/resources/alfresco/messages/email-server-model*.properties src/main/resources/alfresco/messages/email-service*.properties src/main/resources/alfresco/messages/file-folder-service*.properties src/main/resources/alfresco/messages/form-service*.properties src/main/resources/alfresco/messages/forum-model*.properties src/main/resources/alfresco/messages/imap-service*.properties src/main/resources/alfresco/messages/initiate-inplace*.properties src/main/resources/alfresco/messages/invitation-service*.properties src/main/resources/alfresco/messages/lock-service*.properties src/main/resources/alfresco/messages/notification-service*.properties src/main/resources/alfresco/messages/period-provider*.properties src/main/resources/alfresco/messages/permissions-service*.properties src/main/resources/alfresco/messages/publishing-model*.properties src/main/resources/alfresco/messages/publishing-service*.properties src/main/resources/alfresco/messages/quickshare-service*.properties src/main/resources/alfresco/messages/rendition-config*.properties src/main/resources/alfresco/messages/replication*.properties src/main/resources/alfresco/messages/repoadmin-service*.properties src/main/resources/alfresco/messages/reset-password-messages*.properties src/main/resources/alfresco/messages/rule-config*.properties src/main/resources/alfresco/messages/site-model*.properties src/main/resources/alfresco/messages/site-service*.properties src/main/resources/alfresco/messages/slingshot*.properties src/main/resources/alfresco/messages/smartfolder-model*.properties src/main/resources/alfresco/messages/subscription-service*.properties src/main/resources/alfresco/messages/system-messages*.properties src/main/resources/alfresco/messages/system-model*.properties src/main/resources/alfresco/messages/template-service*.properties src/main/resources/alfresco/messages/templates-messages*.properties src/main/resources/alfresco/messages/transfer-model*.properties src/main/resources/alfresco/messages/transfer-service*.properties src/main/resources/alfresco/messages/ui-inplace*.properties src/main/resources/alfresco/messages/webdav-messages*.properties src/main/resources/alfresco/messages/workflow-package-messages*.properties src/main/resources/alfresco/workflow/invitation-moderated-workflow-messages*.properties src/main/resources/alfresco/workflow/invitation-nominated-workflow-messages*.properties src/main/resources/alfresco/workflow/workflow-messages*.properties" -EXCLUDED_FILES="src/main/resources/alfresco/messages/content-service.properties src/main/resources/alfresco/messages/module-messages.properties src/main/resources/alfresco/messages/patch-service.properties src/main/resources/alfresco/messages/repoadmin-interpreter-help.properties src/main/resources/alfresco/messages/schema-update.properties src/main/resources/alfresco/messages/tenant-interpreter-help.properties src/main/resources/alfresco/messages/version-service.properties src/main/resources/alfresco/messages/workflow-interpreter-help.properties src/main/resources/alfresco/alfresco-shared.properties src/main/resources/alfresco/caches.properties src/main/resources/alfresco/repository.properties src/main/resources/alfresco/client/config/repo-clients-apps.properties src/main/resources/alfresco/domain/cache-strategies.properties src/main/resources/alfresco/domain/hibernate-cfg.properties src/main/resources/alfresco/domain/quartz.properties src/main/resources/alfresco/domain/transaction.properties src/main/resources/alfresco/keystore/keystore-passwords.properties src/main/resources/alfresco/keystore/ssl-keystore-passwords.properties src/main/resources/alfresco/keystore/ssl-truststore-passwords.properties src/main/resources/alfresco/metadata/DWGMetadataExtracter.properties src/main/resources/alfresco/metadata/HtmlMetadataExtracter.properties src/main/resources/alfresco/metadata/MailMetadataExtracter.properties src/main/resources/alfresco/metadata/MP3MetadataExtracter.properties src/main/resources/alfresco/metadata/OfficeMetadataExtracter.properties src/main/resources/alfresco/metadata/OpenDocumentMetadataExtracter.properties src/main/resources/alfresco/metadata/OpenOfficeMetadataExtracter.properties src/main/resources/alfresco/metadata/PdfBoxMetadataExtracter.properties src/main/resources/alfresco/metadata/PoiMetadataExtracter.properties src/main/resources/alfresco/metadata/RFC822MetadataExtracter.properties src/main/resources/alfresco/metadata/TikaAudioMetadataExtracter.properties src/main/resources/alfresco/metadata/TikaAutoMetadataExtracter.properties src/main/resources/alfresco/metadata/TikaSpringConfiguredMetadataExtracter.properties src/main/resources/alfresco/subsystems/ActivitiesFeed/default/activities-jobs.properties src/main/resources/alfresco/subsystems/Authentication/alfrescoNtlm/alfresco-authentication.properties src/main/resources/alfresco/subsystems/Authentication/external/external-authentication.properties src/main/resources/alfresco/subsystems/Authentication/kerberos/kerberos-authentication.properties src/main/resources/alfresco/subsystems/Authentication/ldap/ldap-authentication.properties src/main/resources/alfresco/subsystems/Authentication/ldap-ad/ldap-ad-authentication.properties src/main/resources/alfresco/subsystems/Authentication/passthru/passthru-authentication-context.properties src/main/resources/alfresco/subsystems/email/InboundSMTP/inboundSMTP.properties src/main/resources/alfresco/subsystems/email/OutboundSMTP/outboundSMTP.properties src/main/resources/alfresco/subsystems/fileServers/default/file-servers.properties src/main/resources/alfresco/subsystems/imap/default/imap-server.properties src/main/resources/alfresco/subsystems/OOoDirect/default/openoffice-transform.properties src/main/resources/alfresco/subsystems/Replication/default/replication.properties src/main/resources/alfresco/subsystems/Search/noindex/common-search.properties src/main/resources/alfresco/subsystems/Search/noindex/noindex-search.properties src/main/resources/alfresco/subsystems/Search/solr/common-search.properties src/main/resources/alfresco/subsystems/Search/solr/solr-backup.properties src/main/resources/alfresco/subsystems/Search/solr/solr-search.properties src/main/resources/alfresco/subsystems/Search/solr/facet/solr-facets-config.properties src/main/resources/alfresco/subsystems/Search/solr4/common-search.properties src/main/resources/alfresco/subsystems/Search/solr4/solr-backup.properties src/main/resources/alfresco/subsystems/Search/solr4/solr-search.properties src/main/resources/alfresco/subsystems/Search/solr6/common-search.properties src/main/resources/alfresco/subsystems/Search/solr6/solr-backup.properties src/main/resources/alfresco/subsystems/Search/solr6/solr-search.properties src/main/resources/alfresco/subsystems/Subscriptions/default/subscription-service.properties src/main/resources/alfresco/subsystems/Synchronization/default/default-synchronization.properties src/main/resources/alfresco/subsystems/sysAdmin/default/sysadmin-parameter.properties src/main/resources/alfresco/subsystems/thirdparty/default/alfresco-pdf-renderer-transform.properties src/main/resources/alfresco/subsystems/thirdparty/default/imagemagick-transform.properties src/main/resources/alfresco/subsystems/Transformers/default/transformers.properties src/main/resources/org/alfresco/encryption/keystore-parameters.properties src/main/resources/org/alfresco/repo/i18n/testMessages.properties src/main/resources/org/alfresco/repo/module/tool/default-file-mapping.properties src/main/resources/org/alfresco/repo/publishing/facebook/facebook-publishing.properties src/main/resources/org/alfresco/repo/publishing/flickr/flickr-publishing.properties src/main/resources/org/alfresco/repo/publishing/linkedin/linkedin-publishing.properties src/main/resources/org/alfresco/repo/publishing/slideshare/slideshare-publishing.properties src/main/resources/org/alfresco/repo/publishing/twitter/twitter-publishing.properties src/main/resources/org/alfresco/repo/publishing/youtube/youtube-publishing.properties" +EXCLUDED_FILES="src/main/resources/alfresco/messages/content-service.properties src/main/resources/alfresco/messages/module-messages.properties src/main/resources/alfresco/messages/patch-service.properties src/main/resources/alfresco/messages/repoadmin-interpreter-help.properties src/main/resources/alfresco/messages/schema-update.properties src/main/resources/alfresco/messages/tenant-interpreter-help.properties src/main/resources/alfresco/messages/version-service.properties src/main/resources/alfresco/messages/workflow-interpreter-help.properties src/main/resources/alfresco/alfresco-shared.properties src/main/resources/alfresco/caches.properties src/main/resources/alfresco/repository.properties src/main/resources/alfresco/client/config/repo-clients-apps.properties src/main/resources/alfresco/domain/cache-strategies.properties src/main/resources/alfresco/domain/hibernate-cfg.properties src/main/resources/alfresco/domain/quartz.properties src/main/resources/alfresco/domain/transaction.properties src/main/resources/alfresco/keystore/keystore-passwords.properties src/main/resources/alfresco/keystore/ssl-keystore-passwords.properties src/main/resources/alfresco/keystore/ssl-truststore-passwords.properties src/main/resources/alfresco/metadata/DWGMetadataExtracter.properties src/main/resources/alfresco/metadata/HtmlMetadataExtracter.properties src/main/resources/alfresco/metadata/MailMetadataExtracter.properties src/main/resources/alfresco/metadata/MP3MetadataExtracter.properties src/main/resources/alfresco/metadata/OfficeMetadataExtracter.properties src/main/resources/alfresco/metadata/PdfBoxMetadataExtracter.properties src/main/resources/alfresco/metadata/PoiMetadataExtracter.properties src/main/resources/alfresco/metadata/RFC822MetadataExtracter.properties src/main/resources/alfresco/metadata/TikaAudioMetadataExtracter.properties src/main/resources/alfresco/metadata/TikaAutoMetadataExtracter.properties src/main/resources/alfresco/metadata/TikaSpringConfiguredMetadataExtracter.properties src/main/resources/alfresco/subsystems/ActivitiesFeed/default/activities-jobs.properties src/main/resources/alfresco/subsystems/Authentication/alfrescoNtlm/alfresco-authentication.properties src/main/resources/alfresco/subsystems/Authentication/external/external-authentication.properties src/main/resources/alfresco/subsystems/Authentication/kerberos/kerberos-authentication.properties src/main/resources/alfresco/subsystems/Authentication/ldap/ldap-authentication.properties src/main/resources/alfresco/subsystems/Authentication/ldap-ad/ldap-ad-authentication.properties src/main/resources/alfresco/subsystems/Authentication/passthru/passthru-authentication-context.properties src/main/resources/alfresco/subsystems/email/InboundSMTP/inboundSMTP.properties src/main/resources/alfresco/subsystems/email/OutboundSMTP/outboundSMTP.properties src/main/resources/alfresco/subsystems/fileServers/default/file-servers.properties src/main/resources/alfresco/subsystems/imap/default/imap-server.properties src/main/resources/alfresco/subsystems/Replication/default/replication.properties src/main/resources/alfresco/subsystems/Search/noindex/common-search.properties src/main/resources/alfresco/subsystems/Search/noindex/noindex-search.properties src/main/resources/alfresco/subsystems/Search/solr/common-search.properties src/main/resources/alfresco/subsystems/Search/solr/solr-backup.properties src/main/resources/alfresco/subsystems/Search/solr/solr-search.properties src/main/resources/alfresco/subsystems/Search/solr/facet/solr-facets-config.properties src/main/resources/alfresco/subsystems/Search/solr4/common-search.properties src/main/resources/alfresco/subsystems/Search/solr4/solr-backup.properties src/main/resources/alfresco/subsystems/Search/solr4/solr-search.properties src/main/resources/alfresco/subsystems/Search/solr6/common-search.properties src/main/resources/alfresco/subsystems/Search/solr6/solr-backup.properties src/main/resources/alfresco/subsystems/Search/solr6/solr-search.properties src/main/resources/alfresco/subsystems/Subscriptions/default/subscription-service.properties src/main/resources/alfresco/subsystems/Synchronization/default/default-synchronization.properties src/main/resources/alfresco/subsystems/sysAdmin/default/sysadmin-parameter.properties src/main/resources/alfresco/subsystems/thirdparty/default/alfresco-pdf-renderer-transform.properties src/main/resources/alfresco/subsystems/thirdparty/default/imagemagick-transform.properties src/main/resources/alfresco/subsystems/Transformers/default/transformers.properties src/main/resources/org/alfresco/encryption/keystore-parameters.properties src/main/resources/org/alfresco/repo/i18n/testMessages.properties src/main/resources/org/alfresco/repo/module/tool/default-file-mapping.properties src/main/resources/org/alfresco/repo/publishing/facebook/facebook-publishing.properties src/main/resources/org/alfresco/repo/publishing/flickr/flickr-publishing.properties src/main/resources/org/alfresco/repo/publishing/linkedin/linkedin-publishing.properties src/main/resources/org/alfresco/repo/publishing/slideshare/slideshare-publishing.properties src/main/resources/org/alfresco/repo/publishing/twitter/twitter-publishing.properties src/main/resources/org/alfresco/repo/publishing/youtube/youtube-publishing.properties src/main/resources/alfresco/metadata/JodConverterMetadataExtracter.properties src/main/resources/alfresco/subsystems/OOoJodconverter/default/jodconverter.properties" diff --git a/pom.xml b/pom.xml index ddf986410c..532ca8c612 100644 --- a/pom.xml +++ b/pom.xml @@ -466,27 +466,10 @@ 2.4.7 indy - - com.artofsolving - jodconverter - 2.1.0-alfresco-patched - - - org.openoffice - unoil - 3.1.0 - - - ridl - org.openoffice - - - - - org.openoffice - juh - 3.1.0 + org.alfresco + alfresco-jodconverter-core + 3.0.1 net.sf.javamusictag @@ -498,11 +481,6 @@ jmagick 6.6.9 - - org.openoffice - jut - 1.0-alfresco - org.htmlparser htmlparser diff --git a/src/main/java/org/alfresco/filesys/repo/ContentDiskDriver.java b/src/main/java/org/alfresco/filesys/repo/ContentDiskDriver.java index f05ace6719..c6c557854d 100644 --- a/src/main/java/org/alfresco/filesys/repo/ContentDiskDriver.java +++ b/src/main/java/org/alfresco/filesys/repo/ContentDiskDriver.java @@ -2637,7 +2637,7 @@ public class ContentDiskDriver extends AlfrescoTxDiskDriver implements DiskInter { public Pair call() throws IOException { - // Check if the file is an OpenOffice document and hte truncation flag is set + // Check if the file is an OpenOffice document and the truncation flag is set // // Note: Check before the timestamp update diff --git a/src/main/java/org/alfresco/util/JodConfig.java b/src/main/java/org/alfresco/repo/content/JodConverter.java similarity index 64% rename from src/main/java/org/alfresco/util/JodConfig.java rename to src/main/java/org/alfresco/repo/content/JodConverter.java index 2d43de19b4..52c46acf47 100644 --- a/src/main/java/org/alfresco/util/JodConfig.java +++ b/src/main/java/org/alfresco/repo/content/JodConverter.java @@ -2,7 +2,7 @@ * #%L * Alfresco Repository * %% - * Copyright (C) 2005 - 2016 Alfresco Software Limited + * 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 @@ -23,24 +23,21 @@ * along with Alfresco. If not, see . * #L% */ -package org.alfresco.util; - -import java.util.Collection; - -/** - * Supplies OOoJodconverter subsystems config parameters that might clash with the OOoDirect subsystem. - * - * @author Alan Davis - */ -public interface JodConfig -{ - public abstract Collection getPortsCollection(); - - public abstract String getPorts(); - - public abstract void setPorts(String ports); - - public abstract boolean isEnabled(); - - public abstract void setEnabled(boolean enabled); +package org.alfresco.repo.content; + +import org.artofsolving.jodconverter.office.OfficeManager; + +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 true if available, else false + */ + public abstract boolean isAvailable(); } \ No newline at end of file diff --git a/src/main/java/org/alfresco/repo/content/JodConverterSharedInstance.java b/src/main/java/org/alfresco/repo/content/JodConverterSharedInstance.java new file mode 100644 index 0000000000..6a859d3341 --- /dev/null +++ b/src/main/java/org/alfresco/repo/content/JodConverterSharedInstance.java @@ -0,0 +1,524 @@ +/* + * #%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 . + * #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; + +/** + * 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 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 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; + 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); + } + + // Only start the JodConverter instance(s) if the subsystem is enabled. + if (isEnabled() == false) + { + return; + } + + logAllSofficeFilesUnderOfficeHome(); + + try + { + DefaultOfficeManagerConfiguration defaultOfficeMgrConfig = new DefaultOfficeManagerConfiguration(); + if (maxTasksPerProcess != null && maxTasksPerProcess > 0) + { + defaultOfficeMgrConfig.setMaxTasksPerProcess(maxTasksPerProcess); + } + if (officeHome != null) + { + 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(), 2)) + { + logFileInfo(f); + } + } + + private List findSofficePrograms(File searchRoot, List results, int maxRecursionDepth) + { + return this.findSofficePrograms(searchRoot, results, 0, maxRecursionDepth); + } + + private List findSofficePrograms(File searchRoot, List 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; + } +} diff --git a/src/main/java/org/alfresco/repo/content/metadata/DefaultOpenOfficeMetadataWorker.java b/src/main/java/org/alfresco/repo/content/metadata/DefaultOpenOfficeMetadataWorker.java deleted file mode 100644 index 657cc7fa2d..0000000000 --- a/src/main/java/org/alfresco/repo/content/metadata/DefaultOpenOfficeMetadataWorker.java +++ /dev/null @@ -1,148 +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 . - * #L% - */ -package org.alfresco.repo.content.metadata; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.Serializable; -import java.net.ConnectException; -import java.util.HashMap; -import java.util.Map; - -import net.sf.jooreports.openoffice.connection.OpenOfficeConnection; - -import org.alfresco.service.cmr.repository.ContentReader; -import org.alfresco.service.cmr.repository.MimetypeService; -import org.alfresco.util.TempFileProvider; - -import com.sun.star.beans.PropertyValue; -import com.sun.star.beans.XPropertySet; -import com.sun.star.document.XDocumentInfoSupplier; -import com.sun.star.frame.XComponentLoader; -import com.sun.star.lang.XComponent; -import com.sun.star.ucb.XFileIdentifierConverter; -import com.sun.star.uno.UnoRuntime; - -/** - * The class doing the actual work of the OpenOfficeMetadataExtracter, based around an OpenOffice connection. - * - * @author dward - */ -public class DefaultOpenOfficeMetadataWorker implements OpenOfficeMetadataWorker -{ - private static final String KEY_AUTHOR = "author"; - private static final String KEY_TITLE = "title"; - private static final String KEY_DESCRIPTION = "description"; - - private OpenOfficeConnection connection; - private MimetypeService mimetypeService; - - public void setConnection(OpenOfficeConnection connection) - { - this.connection = connection; - } - - /* - * @param mimetypeService the mimetype service. Set this if required. - */ - public void setMimetypeService(MimetypeService mimetypeService) - { - this.mimetypeService = mimetypeService; - } - - /** - * @return Returns true if a connection to the Uno server could be established - */ - public boolean isConnected() - { - return connection.isConnected(); - } - - /* - * (non-Javadoc) - * @seeorg.alfresco.repo.content.metadata.OpenOfficeMetadataWorker#extractRaw(org.alfresco.service.cmr.repository. - * ContentReader) - */ - public Map extractRaw(ContentReader reader) throws Throwable - { - Map rawProperties = new HashMap(17); - - String sourceMimetype = reader.getMimetype(); - - // create temporary files to convert from and to - File tempFromFile = TempFileProvider.createTempFile("OpenOfficeMetadataExtracter-", "." - + this.mimetypeService.getExtension(sourceMimetype)); - - // download the content from the source reader - reader.getContent(tempFromFile); - - String sourceUrl = toUrl(tempFromFile, connection); - - // UNO Interprocess Bridge *should* be thread-safe, but... - XComponentLoader desktop = connection.getDesktop(); - XComponent document = desktop.loadComponentFromURL(sourceUrl, "_blank", 0, new PropertyValue[] - { - property("Hidden", Boolean.TRUE) - }); - if (document == null) - { - throw new FileNotFoundException("could not open source document: " + sourceUrl); - } - try - { - XDocumentInfoSupplier infoSupplier = (XDocumentInfoSupplier) UnoRuntime.queryInterface( - XDocumentInfoSupplier.class, document); - XPropertySet propSet = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, infoSupplier - .getDocumentInfo()); - - rawProperties.put(KEY_TITLE, propSet.getPropertyValue("Title").toString()); - rawProperties.put(KEY_DESCRIPTION, propSet.getPropertyValue("Subject").toString()); - rawProperties.put(KEY_AUTHOR, propSet.getPropertyValue("Author").toString()); - } - finally - { - document.dispose(); - } - // Done - return rawProperties; - } - - public String toUrl(File file, OpenOfficeConnection connection) throws ConnectException - { - Object fcp = connection.getFileContentProvider(); - XFileIdentifierConverter fic = (XFileIdentifierConverter) UnoRuntime.queryInterface( - XFileIdentifierConverter.class, fcp); - return fic.getFileURLFromSystemPath("", file.getAbsolutePath()); - } - - private static PropertyValue property(String name, Object value) - { - PropertyValue property = new PropertyValue(); - property.Name = name; - property.Value = value; - return property; - } -} diff --git a/src/main/java/org/alfresco/repo/content/metadata/OpenOfficeMetadataExtracter.java b/src/main/java/org/alfresco/repo/content/metadata/JodConverterMetadataExtracter.java similarity index 61% rename from src/main/java/org/alfresco/repo/content/metadata/OpenOfficeMetadataExtracter.java rename to src/main/java/org/alfresco/repo/content/metadata/JodConverterMetadataExtracter.java index e7fe24889d..b7400bfe54 100644 --- a/src/main/java/org/alfresco/repo/content/metadata/OpenOfficeMetadataExtracter.java +++ b/src/main/java/org/alfresco/repo/content/metadata/JodConverterMetadataExtracter.java @@ -2,7 +2,7 @@ * #%L * Alfresco Repository * %% - * Copyright (C) 2005 - 2016 Alfresco Software Limited + * 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 @@ -23,76 +23,55 @@ * along with Alfresco. If not, see . * #L% */ -/* - * Copyright (C) 2005 Jesper Steen Møller - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ package org.alfresco.repo.content.metadata; import java.io.Serializable; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import java.util.Map; +import java.util.Set; import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.repo.content.metadata.AbstractMappingMetadataExtracter; +import org.alfresco.repo.content.metadata.OpenOfficeMetadataWorker; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.util.PropertyCheck; /** - * Extracts values from Star Office documents into the following: + * Extracts values from Open Office documents into the following: *
  *   author:                 --      cm:author
  *   title:                  --      cm:title
  *   description:            --      cm:description
  * 
* - * Note - not converted to Apache Tika, as currently Tika - * lacks support for these older formats - * - * @author Jesper Steen Møller + * @author Neil McErlean */ -public class OpenOfficeMetadataExtracter extends AbstractMappingMetadataExtracter implements OpenOfficeMetadataWorker +public class JodConverterMetadataExtracter extends AbstractMappingMetadataExtracter implements OpenOfficeMetadataWorker { - public static String[] SUPPORTED_MIMETYPES = new String[] { - MimetypeMap.MIMETYPE_STAROFFICE5_WRITER, - MimetypeMap.MIMETYPE_STAROFFICE5_IMPRESS, - MimetypeMap.MIMETYPE_OPENOFFICE1_WRITER, - MimetypeMap.MIMETYPE_OPENOFFICE1_IMPRESS - }; - private OpenOfficeMetadataWorker worker; - - public OpenOfficeMetadataExtracter() + private static final Set typedEmptySet = Collections.emptySet(); + + public JodConverterMetadataExtracter() { - super(new HashSet(Arrays.asList(SUPPORTED_MIMETYPES))); + this(typedEmptySet); } - + + public JodConverterMetadataExtracter(Set supportedMimetypes) + { + super(supportedMimetypes); + } + public void setWorker(OpenOfficeMetadataWorker worker) { this.worker = worker; } - /** - * Initialises the bean by establishing an UNO connection - */ @Override public synchronized void init() { - PropertyCheck.mandatory("OpenOfficeMetadataExtracter", "worker", worker); + PropertyCheck.mandatory("JodConverterMetadataExtracter", "worker", worker); // Base initialization super.init(); diff --git a/src/main/java/org/alfresco/repo/content/metadata/JodConverterMetadataExtracterWorker.java b/src/main/java/org/alfresco/repo/content/metadata/JodConverterMetadataExtracterWorker.java new file mode 100644 index 0000000000..299680cb1d --- /dev/null +++ b/src/main/java/org/alfresco/repo/content/metadata/JodConverterMetadataExtracterWorker.java @@ -0,0 +1,275 @@ +/* + * #%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 . + * #L% + */ +package org.alfresco.repo.content.metadata; + +import static org.artofsolving.jodconverter.office.OfficeUtils.SERVICE_DESKTOP; +import static org.artofsolving.jodconverter.office.OfficeUtils.cast; +import static org.artofsolving.jodconverter.office.OfficeUtils.toUrl; + +import java.io.File; +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +import org.alfresco.repo.content.JodConverter; +import org.alfresco.repo.content.metadata.OpenOfficeMetadataWorker; +import org.alfresco.service.cmr.repository.ContentReader; +import org.alfresco.service.cmr.repository.MimetypeService; +import org.alfresco.util.TempFileProvider; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.artofsolving.jodconverter.office.OfficeContext; +import org.artofsolving.jodconverter.office.OfficeException; +import org.artofsolving.jodconverter.office.OfficeTask; + +import com.sun.star.beans.PropertyValue; +import com.sun.star.beans.UnknownPropertyException; +import com.sun.star.beans.XPropertySet; +import com.sun.star.document.XDocumentInfoSupplier; +import com.sun.star.frame.XComponentLoader; +import com.sun.star.io.IOException; +import com.sun.star.lang.IllegalArgumentException; +import com.sun.star.lang.WrappedTargetException; +import com.sun.star.lang.XComponent; +import com.sun.star.task.ErrorCodeIOException; +import com.sun.star.util.CloseVetoException; +import com.sun.star.util.XCloseable; +import com.sun.star.util.XRefreshable; + +public class JodConverterMetadataExtracterWorker implements + OpenOfficeMetadataWorker +{ + /** Logger */ + private static Log logger = LogFactory.getLog(JodConverterMetadataExtracterWorker.class); + + private JodConverter jodc; + private MimetypeService mimetypeService; + + /* + * @param mimetypeService the mimetype service. Set this if required. + */ + public void setMimetypeService(MimetypeService mimetypeService) + { + this.mimetypeService = mimetypeService; + } + + public void setJodConverter(JodConverter jodc) + { + this.jodc = jodc; + } + + /* + * @see org.alfresco.repo.content.metadata.OpenOfficeMetadataWorker#extractRaw + * (org.alfresco.service.cmr.repository. ContentReader) + */ + public Map extractRaw(ContentReader reader) + throws Throwable + { + String sourceMimetype = reader.getMimetype(); + + if (logger.isDebugEnabled()) + { + StringBuilder msg = new StringBuilder(); + msg.append("Extracting metadata content from ") + .append(sourceMimetype); + logger.debug(msg.toString()); + } + + // create temporary files to convert from and to + File tempFile = TempFileProvider.createTempFile(this.getClass() + .getSimpleName() + + "-", "." + mimetypeService.getExtension(sourceMimetype)); + + // download the content from the source reader + reader.getContent(tempFile); + + ResultsCallback callback = new ResultsCallback(); + jodc.getOfficeManager().execute(new ExtractMetadataOfficeTask(tempFile, callback)); + + return callback.getResults(); + } + + public boolean isConnected() + { + // the JodConverter library ensures that the connection is always there. + // If the extracter is not available then the isAvailable call should ensure that it is not used. + return true; + } +} + +class ExtractMetadataOfficeTask implements OfficeTask +{ + /* + * These keys are used by Alfresco to map properties into a content model and do need to + * have lower-case initial letters. + */ + private static final String KEY_AUTHOR = "author"; + private static final String KEY_TITLE = "title"; + private static final String KEY_DESCRIPTION = "description"; + + private static Log logger = LogFactory.getLog(ExtractMetadataOfficeTask.class); + private File inputFile; + private ResultsCallback callback; + + public ExtractMetadataOfficeTask(File inputFile, ResultsCallback callback) + { + this.inputFile = inputFile; + this.callback = callback; + } + + public void execute(OfficeContext context) + { + if (logger.isDebugEnabled()) + { + logger.debug("Extracting metadata from file " + inputFile); + } + + XComponent document = null; + try + { + if (!inputFile.exists()) + { + throw new OfficeException("input document not found"); + } + XComponentLoader loader = cast(XComponentLoader.class, context + .getService(SERVICE_DESKTOP)); + + // Need to set the Hidden property to ensure that OOo GUI does not appear. + PropertyValue hiddenOOo = new PropertyValue(); + hiddenOOo.Name = "Hidden"; + hiddenOOo.Value = Boolean.TRUE; + PropertyValue readOnly = new PropertyValue(); + readOnly.Name = "ReadOnly"; + readOnly.Value = Boolean.TRUE; + + try + { + document = loader.loadComponentFromURL(toUrl(inputFile), "_blank", 0, + new PropertyValue[]{hiddenOOo, readOnly}); + } catch (IllegalArgumentException illegalArgumentException) + { + throw new OfficeException("could not load document: " + + inputFile.getName(), illegalArgumentException); + } catch (ErrorCodeIOException errorCodeIOException) + { + throw new OfficeException("could not load document: " + + inputFile.getName() + "; errorCode: " + + errorCodeIOException.ErrCode, errorCodeIOException); + } catch (IOException ioException) + { + throw new OfficeException("could not load document: " + + inputFile.getName(), ioException); + } + if (document == null) + { + throw new OfficeException("could not load document: " + + inputFile.getName()); + } + XRefreshable refreshable = cast(XRefreshable.class, document); + if (refreshable != null) + { + refreshable.refresh(); + } + + XDocumentInfoSupplier docInfoSupplier = cast(XDocumentInfoSupplier.class, document); + XPropertySet propSet = cast(XPropertySet.class, docInfoSupplier.getDocumentInfo()); + + // The strings below are property names as used by OOo. They need upper-case + // initial letters. + Object author = getPropertyValueIfAvailable(propSet, "Author"); + Object description = getPropertyValueIfAvailable(propSet, "Subject"); + Object title = getPropertyValueIfAvailable(propSet, "Title"); + + Map results = new HashMap(3); + results.put(KEY_AUTHOR, author == null ? null : author.toString()); + results.put(KEY_DESCRIPTION, description == null ? null : description.toString()); + results.put(KEY_TITLE, title == null ? null : title.toString()); + callback.setResults(results); + } catch (OfficeException officeException) + { + throw officeException; + } catch (Exception exception) + { + throw new OfficeException("conversion failed", exception); + } finally + { + if (document != null) + { + XCloseable closeable = cast(XCloseable.class, document); + if (closeable != null) + { + try + { + closeable.close(true); + } catch (CloseVetoException closeVetoException) + { + // whoever raised the veto should close the document + } + } else + { + document.dispose(); + } + } + } + } + + /** + * OOo throws exceptions if we ask for properties that aren't there, so we'll tread carefully. + * + * @param propSet + * @param propertyName property name as used by the OOo API. + * @return the propertyValue if it's there, else null. + * @throws UnknownPropertyException + * @throws WrappedTargetException + */ + private Object getPropertyValueIfAvailable(XPropertySet propSet, String propertyName) + throws UnknownPropertyException, WrappedTargetException + { + if (propSet.getPropertySetInfo().hasPropertyByName(propertyName)) + { + return propSet.getPropertyValue(propertyName); + } + else + { + return null; + } + } +} + +class ResultsCallback +{ + private Map results = new HashMap(); + + public Map getResults() + { + return results; + } + + public void setResults(Map results) + { + this.results = results; + } +} diff --git a/src/main/java/org/alfresco/repo/content/transform/JodContentTransformer.java b/src/main/java/org/alfresco/repo/content/transform/JodContentTransformer.java new file mode 100644 index 0000000000..6dc6dd53f6 --- /dev/null +++ b/src/main/java/org/alfresco/repo/content/transform/JodContentTransformer.java @@ -0,0 +1,82 @@ +/* + * #%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 . + * #L% + */ +package org.alfresco.repo.content.transform; + +import java.io.File; + +import org.artofsolving.jodconverter.document.DocumentFormat; + +import org.alfresco.repo.content.JodConverter; +import org.alfresco.repo.content.transform.ContentTransformerWorker; +import org.alfresco.repo.content.transform.OOoContentTransformerHelper; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.artofsolving.jodconverter.OfficeDocumentConverter; +import org.springframework.beans.factory.InitializingBean; + +/** + * 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 + */ +public class JodContentTransformer extends OOoContentTransformerHelper implements ContentTransformerWorker, InitializingBean +{ + private static Log logger = LogFactory.getLog(JodContentTransformer.class); + + private JodConverter jodconverter; + + public void setJodConverter(JodConverter jodc) + { + this.jodconverter = jodc; + } + + @Override + protected Log getLogger() + { + return logger; + } + + @Override + protected String getTempFilePrefix() + { + return "JodContentTransformer"; + } + + @Override + public boolean isAvailable() + { + return jodconverter.isAvailable(); + } + + @Override + protected void convert(File tempFromFile, DocumentFormat sourceFormat, File tempToFile, + DocumentFormat targetFormat) + { + OfficeDocumentConverter converter = new OfficeDocumentConverter(jodconverter.getOfficeManager()); + converter.convert(tempFromFile, tempToFile); + } +} diff --git a/src/main/java/org/alfresco/repo/content/transform/OOoContentTransformerHelper.java b/src/main/java/org/alfresco/repo/content/transform/OOoContentTransformerHelper.java index 51ac27a5a4..107548d07c 100644 --- a/src/main/java/org/alfresco/repo/content/transform/OOoContentTransformerHelper.java +++ b/src/main/java/org/alfresco/repo/content/transform/OOoContentTransformerHelper.java @@ -36,11 +36,11 @@ import java.io.Reader; import java.io.Writer; import com.sun.star.task.ErrorCodeIOException; -import net.sf.jooreports.converter.DocumentFamily; -import net.sf.jooreports.converter.DocumentFormat; -import net.sf.jooreports.converter.DocumentFormatRegistry; -import net.sf.jooreports.converter.XmlDocumentFormatRegistry; -import net.sf.jooreports.openoffice.connection.OpenOfficeException; +import org.artofsolving.jodconverter.document.DefaultDocumentFormatRegistry; +import org.artofsolving.jodconverter.document.DocumentFamily; +import org.artofsolving.jodconverter.document.DocumentFormat; +import org.artofsolving.jodconverter.document.DocumentFormatRegistry; +import org.artofsolving.jodconverter.document.JsonDocumentFormatRegistry; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.repo.content.MimetypeMap; @@ -55,6 +55,7 @@ import org.apache.pdfbox.exceptions.COSVisitorException; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.edit.PDPageContentStream; +import org.artofsolving.jodconverter.office.OfficeException; import org.springframework.core.io.DefaultResourceLoader; import org.springframework.util.FileCopyUtils; @@ -107,7 +108,7 @@ public abstract class OOoContentTransformerHelper extends ContentTransformerHelp try { InputStream is = resourceLoader.getResource(this.documentFormatsConfiguration).getInputStream(); - formatRegistry = new XmlDocumentFormatRegistry(is); + 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) @@ -119,7 +120,7 @@ public abstract class OOoContentTransformerHelper extends ContentTransformerHelp } else { - formatRegistry = new XmlDocumentFormatRegistry(); + formatRegistry = new DefaultDocumentFormatRegistry(); } } @@ -187,14 +188,14 @@ public abstract class OOoContentTransformerHelper extends ContentTransformerHelp String sourceExtension = mimetypeService.getExtension(sourceMimetype); String targetExtension = mimetypeService.getExtension(targetMimetype); // query the registry for the source format - DocumentFormat sourceFormat = formatRegistry.getFormatByFileExtension(sourceExtension); + DocumentFormat sourceFormat = formatRegistry.getFormatByExtension(sourceExtension); if (sourceFormat == null) { // no document format return false; } // query the registry for the target format - DocumentFormat targetFormat = formatRegistry.getFormatByFileExtension(targetExtension); + DocumentFormat targetFormat = formatRegistry.getFormatByExtension(targetExtension); if (targetFormat == null) { // no document format @@ -202,17 +203,10 @@ public abstract class OOoContentTransformerHelper extends ContentTransformerHelp } // get the family of the target document - DocumentFamily sourceFamily = sourceFormat.getFamily(); + DocumentFamily sourceFamily = sourceFormat.getInputFamily(); // does the format support the conversion - if (!targetFormat.isExportableFrom(sourceFamily)) - { - // unable to export from source family of documents to the target format - return false; - } - else - { - return true; - } + boolean transformable = formatRegistry.getOutputFormats(sourceFamily).contains(targetFormat); // same as: targetFormat.getStoreProperties(sourceFamily) != null + return transformable; } @Override @@ -319,23 +313,23 @@ public abstract class OOoContentTransformerHelper extends ContentTransformerHelp String sourceExtension = mimetypeService.getExtension(sourceMimetype); String targetExtension = mimetypeService.getExtension(targetMimetype); // query the registry for the source format - DocumentFormat sourceFormat = formatRegistry.getFormatByFileExtension(sourceExtension); + 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.getFormatByFileExtension(targetExtension); + 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.getFamily(); + DocumentFamily sourceFamily = sourceFormat.getInputFamily(); // does the format support the conversion - if (!targetFormat.isExportableFrom(sourceFamily)) + if (!formatRegistry.getOutputFormats(sourceFamily).contains(targetFormat)) // same as: targetFormat.getStoreProperties(sourceFamily) == null { throw new ContentIOException( "OpenOffice conversion not supported: \n" + @@ -376,7 +370,7 @@ public abstract class OOoContentTransformerHelper extends ContentTransformerHelp { convert(tempFromFile, sourceFormat, tempToFile, targetFormat); } - catch (OpenOfficeException e) + catch (OfficeException e) { throw new ContentIOException("OpenOffice server conversion failed: \n" + " reader: " + reader + "\n" + diff --git a/src/main/java/org/alfresco/repo/content/transform/OpenOfficeContentTransformerWorker.java b/src/main/java/org/alfresco/repo/content/transform/OpenOfficeContentTransformerWorker.java deleted file mode 100644 index 3168951e4c..0000000000 --- a/src/main/java/org/alfresco/repo/content/transform/OpenOfficeContentTransformerWorker.java +++ /dev/null @@ -1,137 +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 . - * #L% - */ -package org.alfresco.repo.content.transform; - -import java.io.File; - -import net.sf.jooreports.converter.DocumentFormat; -import net.sf.jooreports.openoffice.connection.OpenOfficeConnection; -import net.sf.jooreports.openoffice.converter.AbstractOpenOfficeDocumentConverter; -import net.sf.jooreports.openoffice.converter.OpenOfficeDocumentConverter; - -import org.alfresco.repo.content.MimetypeMap; -import org.alfresco.service.cmr.repository.ContentIOException; -import org.alfresco.service.cmr.repository.ContentReader; -import org.alfresco.util.PropertyCheck; -import org.alfresco.util.SocketOpenOfficeConnection; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.InitializingBean; - -/** - * Makes use of the JOOConverter library to perform - * OpenOffice-driven conversions. - * This requires that OpenOffice be running, but delivers a wider range of transformations - * than Tika is able to (Tika just translates into Text, HTML and XML) - * - * @author Derek Hulley - */ -public class OpenOfficeContentTransformerWorker extends OOoContentTransformerHelper implements ContentTransformerWorker, InitializingBean -{ - private static Log logger = LogFactory.getLog(OpenOfficeContentTransformerWorker.class); - - private OpenOfficeConnection connection; - private AbstractOpenOfficeDocumentConverter converter; - - /** - * @param connection - * the connection that the converter uses - */ - public void setConnection(OpenOfficeConnection connection) - { - this.connection = connection; - } - - /** - * Explicitly set the converter to be used. The converter must use the same connection set in - * {@link #setConnection(OpenOfficeConnection)}. - *

- * If not set, then the OpenOfficeDocumentConverter will be used. - * - * @param converter - * the converter to use. - */ - public void setConverter(AbstractOpenOfficeDocumentConverter converter) - { - this.converter = converter; - } - - @Override - protected Log getLogger() - { - return logger; - } - - @Override - protected String getTempFilePrefix() - { - return "OpenOfficeContentTransformer"; - } - - @Override - public boolean isAvailable() - { - return connection.isConnected(); - } - - @Override - public void afterPropertiesSet() throws Exception - { - PropertyCheck.mandatory("OpenOfficeContentTransformerWorker", "connection", connection); - - super.afterPropertiesSet(); - - // set up the converter - if (converter == null) - { - converter = getDefaultConverter(connection); - } - } - - protected AbstractOpenOfficeDocumentConverter getDefaultConverter(OpenOfficeConnection connection) - { - return (connection instanceof SocketOpenOfficeConnection) - ? ((SocketOpenOfficeConnection)connection).getDefaultConverter() - : new OpenOfficeDocumentConverter(connection); - } - - @Override - protected void convert(File tempFromFile, DocumentFormat sourceFormat, File tempToFile, - DocumentFormat targetFormat) - { - converter.convert(tempFromFile, sourceFormat, tempToFile, targetFormat); - } - - public void saveContentInFile(String sourceMimetype, ContentReader reader, File file) throws ContentIOException - { - // jooconverter does not handle non western chars by default in text files. - // Jodconverter does by setting properties it passes to soffice. - // The following patched method added to jooconverter, addes these properties. - converter.setTextUtf8(MimetypeMap.MIMETYPE_TEXT_PLAIN.equals(sourceMimetype)); - - super.saveContentInFile(sourceMimetype, reader, file); - } -} diff --git a/src/main/java/org/alfresco/repo/content/transform/ProxyContentTransformer.java b/src/main/java/org/alfresco/repo/content/transform/ProxyContentTransformer.java index 71de679ff1..8d00f0b1d5 100644 --- a/src/main/java/org/alfresco/repo/content/transform/ProxyContentTransformer.java +++ b/src/main/java/org/alfresco/repo/content/transform/ProxyContentTransformer.java @@ -1,31 +1,31 @@ -/* - * #%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 . - * #L% - */ +/* + * #%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 . + * #L% + */ package org.alfresco.repo.content.transform; -import net.sf.jooreports.converter.DocumentFormatRegistry; +import org.artofsolving.jodconverter.document.DocumentFormatRegistry; import org.alfresco.api.AlfrescoPublicApi; import org.alfresco.service.cmr.repository.ContentReader; diff --git a/src/main/java/org/alfresco/repo/content/transform/TransformerProperties.java b/src/main/java/org/alfresco/repo/content/transform/TransformerProperties.java index f66a61cb89..7652a805f2 100644 --- a/src/main/java/org/alfresco/repo/content/transform/TransformerProperties.java +++ b/src/main/java/org/alfresco/repo/content/transform/TransformerProperties.java @@ -1,28 +1,28 @@ -/* - * #%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 . - * #L% - */ +/* + * #%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 . + * #L% + */ package org.alfresco.repo.content.transform; import java.io.IOException; @@ -52,7 +52,10 @@ 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; @@ -69,6 +72,12 @@ public class TransformerProperties if (value == null) { value = globalProperties.getProperty(name); + + if (value == null) + { + name = alias(name, JOD_CONVERTER, OPEN_OFFICE); + value = globalProperties.getProperty(name); + } } return value; } @@ -98,21 +107,44 @@ public class TransformerProperties } return defaultProperties; } - + public Set getPropertyNames() { Set propertyNames = new HashSet(subsystem.getPropertyNames()); for (String name: globalProperties.stringPropertyNames()) { - if (name.startsWith(TransformerConfig.PREFIX) && !propertyNames.contains(name)) + if (name.startsWith(TransformerConfig.PREFIX)) { - propertyNames.add(name); + 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 map) { subsystem.setProperties(map); diff --git a/src/main/java/org/alfresco/util/JodConfigImpl.java b/src/main/java/org/alfresco/util/JodConfigImpl.java deleted file mode 100644 index 565a7866b5..0000000000 --- a/src/main/java/org/alfresco/util/JodConfigImpl.java +++ /dev/null @@ -1,71 +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 . - * #L% - */ -package org.alfresco.util; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; - -/** - * Implementation that supplies OOoJodconverter subsystems config parameters that might clash with the OOoDirect subsystem. - * - * @author Alan Davis - */ -public class JodConfigImpl implements JodConfig -{ - private String ports; - private boolean enabled; - - @Override - public Collection getPortsCollection() - { - return Arrays.asList(ports.trim().split("[, ][, ]*")); - } - - @Override - public String getPorts() - { - return getPortsCollection().toString().replaceAll("[ \\[\\]]", ""); - } - - @Override - public void setPorts(String ports) - { - this.ports = ports; - } - - @Override - public boolean isEnabled() - { - return enabled; - } - - @Override - public void setEnabled(boolean enabled) - { - this.enabled = enabled; - } -} diff --git a/src/main/java/org/alfresco/util/JodCoordination.java b/src/main/java/org/alfresco/util/JodCoordination.java deleted file mode 100644 index 2483d46548..0000000000 --- a/src/main/java/org/alfresco/util/JodCoordination.java +++ /dev/null @@ -1,120 +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 . - * #L% - */ -package org.alfresco.util; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * Class coordinates with the OOoJodconverter subsystem so that the OOoDirect subsystem does not - * start up its own soffice process it that would clash with the JOD one. It also does not make a - * connection to a JOD started soffice process. - * - * @author Alan Davis - */ -public class JodCoordination -{ - private static Log logger = LogFactory.getLog(JodCoordination.class); - - private Boolean start; - - private boolean oooEnabled; - private boolean oooLocalhost; - private String oooPort; - private JodConfig jodConfig; - - public void setOooEnabled(boolean oooEnabled) - { - this.oooEnabled = oooEnabled; - } - - public void setOooHost(String oooHost) - { - oooLocalhost = oooHost == null || oooHost.equals(SocketOpenOfficeConnection.DEFAULT_HOST); - } - - public void setOooPort(String oooPort) - { - this.oooPort = oooPort; - } - - public void setJodConfig(JodConfig jodConfig) - { - this.jodConfig = jodConfig; - } - - /** - * Returns {@code true} if the direct OOo should be started. This should not take - * place if both direct ooo and jod are enabled and using the same port. - */ - public boolean startOpenOffice() - { - if (start == null) - { - if (logger.isDebugEnabled()) - { - logger.debug("OOoJodconverter subsystem will "+ - (jodConfig.isEnabled() ? "" : "NOT ") + "start an OpenOffice process"); - } - - start = oooEnabled && oooLocalhost; - if (start) - { - if (jodConfig.isEnabled() && jodConfig.getPortsCollection().contains(oooPort)) - { - start = false; - logger.error("Both OOoDirect and OOoJodconverter subsystems are enabled and have specified " + - "the same port number on the localhost."); - logger.error(" ooo.enabled=true"); - logger.error(" ooo.host=localhost"); - logger.error(" ooo.port=" + oooPort); - logger.error(" jodconverter.portNumbers=" + jodConfig.getPorts()); - logger.error(" jodconverter.enabled=true"); - logger.error("The OOoDirect subsystem will not start its OpenOffice process as a result."); - } - else - { - logger.debug("OOoDirect subsystem will start an OpenOffice process"); - } - } - else - { - logger.debug("OOoDirect subsystem will NOT start an OpenOffice process"); - } - } - return start; - } - - /** - * Returns {@code true} if the direct OOo connection listener should be started. This - * should only take place if a remote host is being used or the direct OOo will be started - * on the local host. - */ - public boolean startListener() - { - return (oooEnabled && !oooLocalhost) || startOpenOffice(); - } -} diff --git a/src/main/java/org/alfresco/util/JodCoordinationBoolean.java b/src/main/java/org/alfresco/util/JodCoordinationBoolean.java deleted file mode 100644 index 271de68a16..0000000000 --- a/src/main/java/org/alfresco/util/JodCoordinationBoolean.java +++ /dev/null @@ -1,68 +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 . - * #L% - */ -package org.alfresco.util; - -import org.alfresco.util.bean.BooleanBean; - -/** - * Wraps a {@link org.alfresco.util.JodCoordination} object to return one of its boolean methods, - * so that it may be used as the input to another bean. - * - * @author Alan Davis - */ -public class JodCoordinationBoolean implements BooleanBean -{ - private JodCoordination jodCoordination; - private String returnValue; - - public void setJodCoordination(JodCoordination jodCoordination) - { - this.jodCoordination = jodCoordination; - } - - public void setReturnValue(String returnValue) - { - this.returnValue = returnValue; - } - - @Override - public boolean isTrue() - { - if ("startOpenOffice".equals(returnValue)) - { - return jodCoordination.startOpenOffice(); - } - else if ("startListener".equals(returnValue)) - { - return jodCoordination.startListener(); - } - else - { - throw new IllegalArgumentException("Expected \"startOpenOffice\" or \"startListener\" " + - "as the returnValue property, but it was \""+returnValue+"\""); - } - } -} diff --git a/src/main/java/org/alfresco/util/OpenOfficeCommandEnv.java b/src/main/java/org/alfresco/util/OpenOfficeCommandEnv.java deleted file mode 100644 index e96b45fbaf..0000000000 --- a/src/main/java/org/alfresco/util/OpenOfficeCommandEnv.java +++ /dev/null @@ -1,70 +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 . - * #L% - */ -package org.alfresco.util; - -import java.io.File; -import java.io.IOException; -import java.util.AbstractMap; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.util.OpenOfficeURI; -import org.alfresco.util.exec.RuntimeExec; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * A map giving the environment openoffice or libreoffice commands require to start. - * - * @author Alan Davis - */ -public class OpenOfficeCommandEnv extends AbstractMap -{ - private static final Log logger = LogFactory.getLog(OpenOfficeCommandLine.class); - private static final String DYLD_LIBRARY_PATH = "DYLD_LIBRARY_PATH"; - - private Map map = new HashMap(System.getenv()); - private OpenOfficeVariant variant = new OpenOfficeVariant(); - - public OpenOfficeCommandEnv(String exe) throws IOException - { - if (variant.isMac()) - { - map.remove(DYLD_LIBRARY_PATH); - logger.debug("Removing $DYLD_LIBRARY_PATH from the environment so that LibreOffice/OpenOffice will start on Mac."); - } - } - - @Override - public Set> entrySet() - { - return map.entrySet(); - } -} diff --git a/src/main/java/org/alfresco/util/OpenOfficeConnectionEvent.java b/src/main/java/org/alfresco/util/OpenOfficeConnectionEvent.java deleted file mode 100644 index e6a517dfdc..0000000000 --- a/src/main/java/org/alfresco/util/OpenOfficeConnectionEvent.java +++ /dev/null @@ -1,63 +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 . - * #L% - */ -package org.alfresco.util; - -import java.util.Map; - -import org.springframework.context.ApplicationEvent; - -/** - * A class of event that notifies the listener of the status of the Open Office Connection. Useful for Monitoring - * purposes. - * - * @author dward - */ -public class OpenOfficeConnectionEvent extends ApplicationEvent -{ - private static final long serialVersionUID = 8834274840220309384L; - - /** - * The Constructor. - * - * @param metaData - * the meta data map - */ - public OpenOfficeConnectionEvent(Map metaData) - { - super(metaData); - } - - /** - * Gets the meta data map. - * - * @return the meta data map - */ - @SuppressWarnings("unchecked") - public Map getMetaData() - { - return (Map) getSource(); - } -} diff --git a/src/main/java/org/alfresco/util/OpenOfficeConnectionTester.java b/src/main/java/org/alfresco/util/OpenOfficeConnectionTester.java deleted file mode 100644 index 44e412e09d..0000000000 --- a/src/main/java/org/alfresco/util/OpenOfficeConnectionTester.java +++ /dev/null @@ -1,340 +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 . - * #L% - */ -package org.alfresco.util; - -import java.lang.reflect.Method; -import java.net.ConnectException; -import java.util.Map; -import java.util.TreeMap; -import java.util.concurrent.Semaphore; - -import net.sf.jooreports.openoffice.connection.AbstractOpenOfficeConnection; -import net.sf.jooreports.openoffice.connection.OpenOfficeConnection; - -import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.repo.content.metadata.MetadataExtracterRegistry; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.quartz.Job; -import org.quartz.JobDataMap; -import org.quartz.JobExecutionContext; -import org.quartz.JobExecutionException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationEvent; -import org.springframework.extensions.surf.util.AbstractLifecycleBean; -import org.springframework.extensions.surf.util.I18NUtil; - -import com.sun.star.registry.RegistryValueType; -import com.sun.star.registry.XRegistryKey; -import com.sun.star.registry.XSimpleRegistry; -import com.sun.star.uno.UnoRuntime; - -/** - * A bootstrap class that checks for the presence of a valid OpenOffice connection, as provided by the - * net.sf.jooreports.openoffice.connection.OpenOfficeConnection implementations. - * - * @author Derek Hulley - */ -public class OpenOfficeConnectionTester extends AbstractLifecycleBean -{ - private static final String ATTRIBUTE_AVAILABLE = "available"; - private static final String INFO_CONNECTION_VERIFIED = "system.openoffice.info.connection_verified"; - private static final String ERR_CONNECTION_FAILED = "system.openoffice.err.connection_failed"; - private static final String ERR_CONNECTION_LOST = "system.openoffice.err.connection_lost"; - private static final String ERR_CONNECTION_REMADE = "system.openoffice.err.connection_remade"; - - private static Log logger = LogFactory.getLog(OpenOfficeConnectionTester.class); - - private OpenOfficeConnection connection; - private Map openOfficeMetadata = new TreeMap(); - private boolean strict; - - private Semaphore singleThreadSemaphore = new Semaphore(1); - - public OpenOfficeConnectionTester() - { - this.strict = false; - } - - /** - * @param connection the OpenOffice connection. - */ - public void setConnection(OpenOfficeConnection connection) - { - this.connection = connection; - } - - /** - * @param strict set to true to generate a failure if the connection is not connected - * during the {@link #checkConnection() connection check}, or false to just issue - * a warning. The default is false. - */ - public void setStrict(boolean strict) - { - this.strict = strict; - } - - /** - * @see #checkConnection() - */ - @Override - protected void onBootstrap(ApplicationEvent event) - { - if (connection instanceof SocketOpenOfficeConnection && ((SocketOpenOfficeConnection)connection).isEnabled()) - { - checkConnection(); - ((ApplicationContext) event.getSource()).publishEvent(new OpenOfficeConnectionEvent(this.openOfficeMetadata)); - } - } - - /** - * Disconnect - */ - @Override - protected void onShutdown(ApplicationEvent event) - { - if(connection != null) - { - if(connection.isConnected()) - { - connection.disconnect(); - } - } - } - - /** - * Perform the actual connection check. If this component is {@link #setStrict(boolean) strict}, - * then a disconnected {@link #setConnection(OpenOfficeConnection) connection} will result in a - * runtime exception being generated. - */ - private void checkConnection() - { - String connectedMessage = I18NUtil.getMessage(INFO_CONNECTION_VERIFIED); - boolean connected = testAndConnect(); - OpenOfficeConnectionTesterJob.wasConnected = Boolean.valueOf(connected); - if (connected) - { - // the connection is fine - logger.debug(connectedMessage); - return; - } - // now we have to either fail or report the connection - String msg = I18NUtil.getMessage(ERR_CONNECTION_FAILED); - if (strict) - { - throw new AlfrescoRuntimeException(msg); - } - else - { - logger.warn(msg); - } - } - - /** - * Calls {@link #testAndConnect()} if no other Threads are currently calling it. - * As a result we should NOT get a queue of Threads from the Quartz scheduler hanging - * one after another, if OpenOffice is taking a long time responding or waiting for the - * connection timeout. This way we get one timeout rather than multiple timeouts. ALF-15406 - * @return {code null} if another Thread is checking the connection or the result from - * {@link #testAndConnect()}. - */ - public Boolean testAndConnectNoQueuing() - { - boolean checking = false; - try - { - checking = singleThreadSemaphore.tryAcquire(); - return checking ? testAndConnect() : null; - } - finally - { - if (checking) - { - singleThreadSemaphore.release(); - } - } - } - - public boolean testAndConnect() - { - synchronized (this.openOfficeMetadata) - { - PropertyCheck.mandatory(this, "connection", connection); - if (!connection.isConnected()) - { - try - { - connection.connect(); - } - catch (ConnectException e) - { - // No luck - this.openOfficeMetadata.clear(); - this.openOfficeMetadata.put(ATTRIBUTE_AVAILABLE, Boolean.FALSE); - return false; - } - } - - // Let's try to get at the version metadata - Boolean lastAvailability = (Boolean)this.openOfficeMetadata.get(ATTRIBUTE_AVAILABLE); - if (lastAvailability == null || !lastAvailability.booleanValue()) - { - this.openOfficeMetadata.put(ATTRIBUTE_AVAILABLE, Boolean.TRUE); - try - { - // We have to peak inside the connection class to get the service we want! - Method getServiceMethod = AbstractOpenOfficeConnection.class.getDeclaredMethod("getService", - String.class); - getServiceMethod.setAccessible(true); - Object configurationRegistry = getServiceMethod.invoke(connection, - "com.sun.star.configuration.ConfigurationRegistry"); - XSimpleRegistry registry = (XSimpleRegistry) UnoRuntime.queryInterface( - com.sun.star.registry.XSimpleRegistry.class, configurationRegistry); - registry.open("org.openoffice.Setup", true, false); - XRegistryKey root = registry.getRootKey(); - XRegistryKey product = root.openKey("Product"); - for (XRegistryKey key : product.openKeys()) - { - switch (key.getValueType().getValue()) - { - case RegistryValueType.LONG_value: - openOfficeMetadata.put(key.getKeyName(), key.getLongValue()); - break; - case RegistryValueType.ASCII_value: - openOfficeMetadata.put(key.getKeyName(), key.getAsciiValue()); - break; - case RegistryValueType.STRING_value: - openOfficeMetadata.put(key.getKeyName(), key.getStringValue()); - break; - } - } - registry.close(); - } - catch (com.sun.star.uno.RuntimeException oooRuntimeException) - { - // ALF-5747 discusses an OOo problem whereby an interface component was not implemented & therefore version - // information cannot be retrieved. This does not seem to affect the operation of the OOo process. - // If we see this exception, which occurs in OOo 3.3.0, we'll shorten the exception log & make it friendlier. - - final String exceptionMessage = oooRuntimeException.getMessage(); - if (exceptionMessage != null && exceptionMessage.contains("com.sun.star.configuration.ConfigurationRegistry: not implemented")) - { - logger.warn("Error trying to query Open Office version information. " + - "OpenOffice.org's ConfigurationRegistry not implemented in this version of OOo. This should not affect the operation of OOo."); - // We have intentionally not logged the exception object here. - } - else - { - logger.warn("Error trying to query Open Office version information", oooRuntimeException); - } - } - catch (Exception e) - { - logger.warn("Error trying to query Open Office version information", e); - } - } - } - return true; - } - - /** - * Quartz job that checks an OpenOffice connection. - * - * @author Derek Hulley - * @since 2.1.2 - */ - public static class OpenOfficeConnectionTesterJob implements Job - { - private static volatile Boolean wasConnected; - - public OpenOfficeConnectionTesterJob() - { - } - - /** - * Check the connection. - * @see OpenOfficeConnectionTester#checkConnection() - */ - public synchronized void execute(JobExecutionContext context) throws JobExecutionException - { - /* - * Synchronized just in case of overzelous triggering. - */ - - JobDataMap jobData = context.getJobDetail().getJobDataMap(); - // Get the connecion tester - Object openOfficeConnectionTesterObj = jobData.get("openOfficeConnectionTester"); - if (openOfficeConnectionTesterObj == null || !(openOfficeConnectionTesterObj instanceof OpenOfficeConnectionTester)) - { - throw new AlfrescoRuntimeException("OpenOfficeConnectionJob data must contain valid 'openOfficeConnectionTester' reference"); - } - OpenOfficeConnectionTester openOfficeConnectionTester = (OpenOfficeConnectionTester) openOfficeConnectionTesterObj; - - // Get the extractor and transformer registries. These are not mandatory. - Object metadataExractorRegistryObj = jobData.get("metadataExractorRegistry"); - MetadataExtracterRegistry metadataExtracterRegistry = null; - if (metadataExractorRegistryObj != null && (metadataExractorRegistryObj instanceof MetadataExtracterRegistry)) - { - metadataExtracterRegistry = (MetadataExtracterRegistry) metadataExractorRegistryObj; - } - - // Now ping the connection. It doesn't matter if it fails or not. - // If there is another Thread already checking. Lets not block and then potentially wait for a timeout. - Boolean connected = openOfficeConnectionTester.testAndConnectNoQueuing(); - if (connected != null) - { - // Now log, if necessary - if (OpenOfficeConnectionTesterJob.wasConnected == null) - { - // This is the first pass - } - else if (OpenOfficeConnectionTesterJob.wasConnected.booleanValue() == connected) - { - // Nothing changed since last time - } - else - { - if (connected) - { - // This is reported as a warning as admins must be aware that it is bouncing - logger.info(I18NUtil.getMessage(ERR_CONNECTION_REMADE)); - } - else - { - logger.error(I18NUtil.getMessage(ERR_CONNECTION_LOST)); - } - // The value changed so ensure that the registries are bounced - if (metadataExtracterRegistry != null) - { - metadataExtracterRegistry.resetCache(); - } - } - // Record the state - OpenOfficeConnectionTesterJob.wasConnected = Boolean.valueOf(connected); - } - } - } -} diff --git a/src/main/java/org/alfresco/util/SocketOpenOfficeConnection.java b/src/main/java/org/alfresco/util/SocketOpenOfficeConnection.java deleted file mode 100644 index 65632d93ca..0000000000 --- a/src/main/java/org/alfresco/util/SocketOpenOfficeConnection.java +++ /dev/null @@ -1,71 +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 . - * #L% - */ -package org.alfresco.util; - -import org.alfresco.util.bean.BooleanBean; - -import net.sf.jooreports.openoffice.converter.AbstractOpenOfficeDocumentConverter; -import net.sf.jooreports.openoffice.converter.OpenOfficeDocumentConverter; -import net.sf.jooreports.openoffice.converter.StreamOpenOfficeDocumentConverter; - -public class SocketOpenOfficeConnection extends net.sf.jooreports.openoffice.connection.SocketOpenOfficeConnection -{ - private boolean defaultHost = true; - private boolean enabled = true; - - public SocketOpenOfficeConnection() { - super(); - } - - public SocketOpenOfficeConnection(int port) { - super(port); - } - - public SocketOpenOfficeConnection(String host, int port) { - super(host, port); - defaultHost = DEFAULT_HOST.equals(host); - } - - public AbstractOpenOfficeDocumentConverter getDefaultConverter() - { - return defaultHost - ? new OpenOfficeDocumentConverter(this) - : new StreamOpenOfficeDocumentConverter(this); - } - - public void setEnabledFromBean(BooleanBean enabled) - { - this.enabled = enabled.isTrue(); - } - - public boolean isConnected() { - return enabled && super.isConnected(); - } - - public boolean isEnabled() { - return enabled; - } -} diff --git a/src/main/resources/alfresco-global.properties.sample b/src/main/resources/alfresco-global.properties.sample index 3d81052a02..ff33a4b15c 100644 --- a/src/main/resources/alfresco-global.properties.sample +++ b/src/main/resources/alfresco-global.properties.sample @@ -17,9 +17,7 @@ # # External locations #------------- -#ooo.exe=soffice -#ooo.enabled=false -#jodconverter.officeHome=./OpenOffice.org +#jodconverter.officeHome=/usr/lib64/libreoffice #jodconverter.portNumbers=8101 #jodconverter.enabled=true #img.root=./ImageMagick diff --git a/src/main/resources/alfresco/bootstrap-context.xml b/src/main/resources/alfresco/bootstrap-context.xml index 3fae856eb3..cc299c246b 100644 --- a/src/main/resources/alfresco/bootstrap-context.xml +++ b/src/main/resources/alfresco/bootstrap-context.xml @@ -311,16 +311,26 @@ - + + true + + + + + + + + + + - - + diff --git a/src/main/resources/alfresco/content-services-context.xml b/src/main/resources/alfresco/content-services-context.xml index 3940363b1e..400c8b5b49 100644 --- a/src/main/resources/alfresco/content-services-context.xml +++ b/src/main/resources/alfresco/content-services-context.xml @@ -275,44 +275,6 @@ - - - - OOoJodconverter - - - jodConfig - - - - org.alfresco.util.JodConfig - - - - - - false - - - - - - - - - - - - extracter.worker.OpenOffice - - - - org.alfresco.repo.content.metadata.OpenOfficeMetadataWorker - - - - @@ -378,11 +340,6 @@ - - - - - @@ -606,13 +563,39 @@ - - + + - + - transformer.worker.OpenOffice + extracter.worker.JodConverter + + + + org.alfresco.repo.content.metadata.OpenOfficeMetadataWorker + + + + + + + + + + + + + + + + + + transformer.worker.JodConverter @@ -621,9 +604,11 @@ - + - + diff --git a/src/main/resources/alfresco/extension/custom-log4j.properties.sample b/src/main/resources/alfresco/extension/custom-log4j.properties.sample index 18027bc568..7746d6f5dd 100644 --- a/src/main/resources/alfresco/extension/custom-log4j.properties.sample +++ b/src/main/resources/alfresco/extension/custom-log4j.properties.sample @@ -1,3 +1,3 @@ -#log4j.logger.org.alfresco.repo.content.transform.TransformerDebug=debug -#log4j.logger.org.alfresco.util.exec.RuntimeExecBootstrapBean=debug -#log4j.logger.org.alfresco.util.exec.RuntimeExec=debug \ No newline at end of file +log4j.logger.org.alfresco.repo.content.transform.TransformerDebug=debug +log4j.logger.org.alfresco.util.exec.RuntimeExecBootstrapBean=debug +log4j.logger.org.alfresco.util.exec.RuntimeExec=debug \ No newline at end of file diff --git a/src/main/resources/alfresco/extension/pdfminer-transform-context.xml.sample b/src/main/resources/alfresco/extension/pdfminer-transform-context.xml.sample index 5907bc8b42..26b2fe18b9 100644 --- a/src/main/resources/alfresco/extension/pdfminer-transform-context.xml.sample +++ b/src/main/resources/alfresco/extension/pdfminer-transform-context.xml.sample @@ -23,24 +23,6 @@ - - - - - - - - - - - - application/pdf - - - - - - @@ -88,11 +86,11 @@ - - + + - + diff --git a/src/main/resources/alfresco/metadata/OpenOfficeMetadataExtracter.properties b/src/main/resources/alfresco/metadata/JodConverterMetadataExtracter.properties similarity index 64% rename from src/main/resources/alfresco/metadata/OpenOfficeMetadataExtracter.properties rename to src/main/resources/alfresco/metadata/JodConverterMetadataExtracter.properties index dc8e947e21..fd4bc33317 100644 --- a/src/main/resources/alfresco/metadata/OpenOfficeMetadataExtracter.properties +++ b/src/main/resources/alfresco/metadata/JodConverterMetadataExtracter.properties @@ -1,12 +1,12 @@ -# -# OpenOfficeMetadataExtracter - default mapping -# -# author: Derek Hulley - -# Namespaces -namespace.prefix.cm=http://www.alfresco.org/model/content/1.0 - -# Mappings -author=cm:author -title=cm:title -description=cm:description +# +# JodConverterMetadataExtracter - default mapping +# +# author: Neil McErlean + +# Namespaces +namespace.prefix.cm=http://www.alfresco.org/model/content/1.0 + +# Mappings +author=cm:author +title=cm:title +description=cm:description diff --git a/src/main/resources/alfresco/mimetype/jodconverter-document-formats.json b/src/main/resources/alfresco/mimetype/jodconverter-document-formats.json new file mode 100644 index 0000000000..8af372aa19 --- /dev/null +++ b/src/main/resources/alfresco/mimetype/jodconverter-document-formats.json @@ -0,0 +1,339 @@ +[ + { + "name": "Portable Document Format", + "extension": "pdf", + "mediaType": "application/pdf", + "storePropertiesByFamily": { + "DRAWING": {"FilterName": "draw_pdf_Export"}, + "SPREADSHEET": {"FilterName": "calc_pdf_Export"}, + "PRESENTATION": {"FilterName": "impress_pdf_Export"}, + "TEXT": {"FilterName": "writer_pdf_Export"} + } + }, + { + "name": "Macromedia Flash", + "extension": "swf", + "mediaType": "application/x-shockwave-flash", + "storePropertiesByFamily": { + "DRAWING": {"FilterName": "draw_flash_Export"}, + "PRESENTATION": {"FilterName": "impress_flash_Export"} + } + }, + { + "name": "HTML", + "extension": "html", + "mediaType": "text/html", + "inputFamily": "TEXT", + "storePropertiesByFamily": { + "SPREADSHEET": {"FilterName": "HTML (StarCalc)"}, + "PRESENTATION": {"FilterName": "impress_html_Export"}, + "TEXT": {"FilterName": "HTML (StarWriter)"} + } + }, + { + "name": "OpenDocument Text", + "extension": "odt", + "mediaType": "application/vnd.oasis.opendocument.text", + "inputFamily": "TEXT", + "storePropertiesByFamily": {"TEXT": {"FilterName": "writer8"}} + }, + { + "name": "OpenDocument Text Template", + "extension": "ott", + "mediaType": "application/vnd.oasis.opendocument.text-template", + "inputFamily": "TEXT", + "storePropertiesByFamily": {"TEXT": {"FilterName": "writer8"}} + }, + { + "name": "OpenOffice.org 1.0 Text Document", + "extension": "sxw", + "mediaType": "application/vnd.sun.xml.writer", + "inputFamily": "TEXT", + "storePropertiesByFamily": {"TEXT": {"FilterName": "StarOffice XML (Writer)"}} + }, + { + "name": "OpenOffice.org 1.0 Text Document Template", + "extension": "stw", + "mediaType": "application/vnd.sun.xml.writer.template", + "inputFamily": "TEXT", + "storePropertiesByFamily": {"TEXT": {"FilterName": "StarOffice XML (Writer)"}} + }, + { + "name": "Microsoft Word", + "extension": "doc", + "mediaType": "application/msword", + "inputFamily": "TEXT", + "storePropertiesByFamily": {"TEXT": {"FilterName": "MS Word 97"}} + }, + { + "name": "Microsoft Word 2007 XML", + "extension": "docx", + "mediaType": "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + "inputFamily": "TEXT", + "storePropertiesByFamily": {"TEXT": {"FilterName": "MS Word 2007"}} + }, + { + "name": "Microsoft Word 2007 macro-enabled document", + "extension": "docm", + "mediaType": "application/vnd.ms-word.document.macroEnabled.12", + "inputFamily": "TEXT", + "storePropertiesByFamily": {"TEXT": {"FilterName": "MS Word 2007"}} + }, + { + "name": "Microsoft Word template 2007", + "extension": "dotx", + "mediaType": "application/vnd.openxmlformats-officedocument.wordprocessingml.template", + "inputFamily": "TEXT", + "storePropertiesByFamily": {"TEXT": {"FilterName": "MS Word 2007"}} + }, + { + "name": "Microsoft Word 2007 macro-enabled document template", + "extension": "dotm", + "mediaType": "application/vnd.ms-word.template.macroEnabled.12", + "inputFamily": "TEXT", + "storePropertiesByFamily": {"TEXT": {"FilterName": "MS Word 2007"}} + }, + { + "name": "WordPerfect", + "extension": "wpd", + "mediaType": "application/wordperfect", + "inputFamily": "TEXT", + "storePropertiesByFamily": {"TEXT": {"FilterName": "WordPerfect"}} + }, + { + "name": "Rich Text Format", + "extension": "rtf", + "mediaType": "text/rtf", + "inputFamily": "TEXT", + "storePropertiesByFamily": {"TEXT": {"FilterName": "Rich Text Format"}} + }, + { + "name": "Plain Text", + "extension": "txt", + "mediaType": "text/plain", + "inputFamily": "TEXT", + "loadProperties": { + "FilterName": "Text (encoded)", + "FilterOptions": "utf8" + }, + "storePropertiesByFamily": {"TEXT": { + "FilterName": "Text (encoded)", + "FilterOptions": "utf8" + }} + }, + { + "name": "MediaWiki wikitext", + "extension": "wiki", + "mediaType": "text/x-wiki", + "storePropertiesByFamily": {"TEXT": {"FilterName": "MediaWiki"}} + }, + { + "name": "OpenDocument Spreadsheet", + "extension": "ods", + "mediaType": "application/vnd.oasis.opendocument.spreadsheet", + "inputFamily": "SPREADSHEET", + "storePropertiesByFamily": {"SPREADSHEET": {"FilterName": "calc8"}} + }, + { + "name": "OpenDocument Spreadsheet Template", + "extension": "ots", + "mediaType": "application/vnd.oasis.opendocument.spreadsheet-template", + "inputFamily": "SPREADSHEET", + "storePropertiesByFamily": {"SPREADSHEET": {"FilterName": "calc8"}} + }, + { + "name": "OpenOffice.org 1.0 Spreadsheet", + "extension": "sxc", + "mediaType": "application/vnd.sun.xml.calc", + "inputFamily": "SPREADSHEET", + "storePropertiesByFamily": {"SPREADSHEET": {"FilterName": "StarOffice XML (Calc)"}} + }, + { + "name": "OpenOffice.org 1.0 Spreadsheet Template", + "extension": "stc", + "mediaType": "application/vnd.sun.xml.calc.template", + "inputFamily": "SPREADSHEET", + "storePropertiesByFamily": {"SPREADSHEET": {"FilterName": "StarOffice XML (Calc)"}} + }, + { + "name": "Microsoft Excel", + "extension": "xls", + "mediaType": "application/vnd.ms-excel", + "inputFamily": "SPREADSHEET", + "storePropertiesByFamily": {"SPREADSHEET": {"FilterName": "MS Excel 97"}} + }, + { + "name": "Microsoft Excel 2007 XML", + "extension": "xlsx", + "mediaType": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + "inputFamily": "SPREADSHEET", + "storePropertiesByFamily": {"SPREADSHEET": {"FilterName": "MS Excel 2007"}} + }, + { + "name": "Microsoft Excel template 2007", + "extension": "xltx", + "mediaType": "application/vnd.openxmlformats-officedocument.spreadsheetml.template", + "inputFamily": "SPREADSHEET", + "storePropertiesByFamily": {"SPREADSHEET": {"FilterName": "MS Excel 2007"}} + }, + { + "name": "Microsoft Excel 2007 macro-enabled workbook", + "extension": "xlsm", + "mediaType": "application/vnd.ms-excel.sheet.macroEnabled.12", + "inputFamily": "SPREADSHEET", + "storePropertiesByFamily": {"SPREADSHEET": {"FilterName": "MS Excel 2007"}} + }, + { + "name": "Microsoft Excel 2007 macro-enabled workbook template", + "extension": "application/vnd.ms-excel.template.macroEnabled.12", + "mediaType": "xltm", + "inputFamily": "SPREADSHEET", + "storePropertiesByFamily": {"SPREADSHEET": {"FilterName": "MS Excel 2007"}} + }, + { + "name": "Microsoft Excel 2007 binary workbook", + "extension": "xlsb", + "mediaType": "application/vnd.ms-excel.sheet.binary.macroEnabled.12", + "inputFamily": "SPREADSHEET", + "storePropertiesByFamily": {"SPREADSHEET": {"FilterName": "MS Excel 2007"}} + }, + { + "name": "Comma Separated Values", + "extension": "csv", + "mediaType": "text/csv", + "inputFamily": "SPREADSHEET", + "loadProperties": { + "FilterName": "Text - txt - csv (StarCalc)", + "FilterOptions": "44,34,0" + }, + "storePropertiesByFamily": {"SPREADSHEET": { + "FilterName": "Text - txt - csv (StarCalc)", + "FilterOptions": "44,34,0" + }} + }, + { + "name": "Tab Separated Values", + "extension": "tsv", + "mediaType": "text/tab-separated-values", + "inputFamily": "SPREADSHEET", + "loadProperties": { + "FilterName": "Text - txt - csv (StarCalc)", + "FilterOptions": "9,34,0" + }, + "storePropertiesByFamily": {"SPREADSHEET": { + "FilterName": "Text - txt - csv (StarCalc)", + "FilterOptions": "9,34,0" + }} + }, + { + "name": "OpenDocument Presentation", + "extension": "odp", + "mediaType": "application/vnd.oasis.opendocument.presentation", + "inputFamily": "PRESENTATION", + "storePropertiesByFamily": {"PRESENTATION": {"FilterName": "impress8"}} + }, + { + "name": "OpenDocument Presentation Template", + "extension": "otp", + "mediaType": "application/vnd.oasis.opendocument.presentation-template", + "inputFamily": "PRESENTATION", + "storePropertiesByFamily": {"PRESENTATION": {"FilterName": "impress8"}} + }, + { + "name": "OpenOffice.org 1.0 Presentation", + "extension": "sxi", + "mediaType": "application/vnd.sun.xml.impress", + "inputFamily": "PRESENTATION", + "storePropertiesByFamily": {"PRESENTATION": {"FilterName": "StarOffice XML (Impress)"}} + }, + { + "name": "OpenOffice.org 1.0 Presentation Template", + "extension": "sti", + "mediaType": "application/vnd.sun.xml.impress.template", + "inputFamily": "PRESENTATION", + "storePropertiesByFamily": {"PRESENTATION": {"FilterName": "StarOffice XML (Impress)"}} + }, + { + "name": "Microsoft PowerPoint", + "extension": "ppt", + "mediaType": "application/vnd.ms-powerpoint", + "inputFamily": "PRESENTATION", + "storePropertiesByFamily": {"PRESENTATION": {"FilterName": "MS PowerPoint 97"}} + }, + { + "name": "Microsoft PowerPoint 2007 XML", + "extension": "pptx", + "mediaType": "application/vnd.openxmlformats-officedocument.presentationml.presentation", + "inputFamily": "PRESENTATION", + "storePropertiesByFamily": {"PRESENTATION": {"FilterName": "MS PowerPoint 2007"}} + }, + { + "name": "Microsoft owerPoint 2007 macro-enabled presentation", + "extension": "pptm", + "mediaType": "application/vnd.ms-powerpoint.presentation.macroEnabled.12", + "inputFamily": "PRESENTATION", + "storePropertiesByFamily": {"PRESENTATION": {"FilterName": "MS PowerPoint 2007"}} + }, + { + "name": "Microsoft PowerPoint 2007 template", + "extension": "potx", + "mediaType": "application/vnd.openxmlformats-officedocument.presentationml.template", + "inputFamily": "PRESENTATION", + "storePropertiesByFamily": {"PRESENTATION": {"FilterName": "MS PowerPoint 2007"}} + }, + { + "name": "Microsoft PowerPoint 2007 macro-enabled presentation template", + "extension": "potm", + "mediaType": "application/vnd.ms-powerpoint.template.macroEnabled.12", + "inputFamily": "PRESENTATION", + "storePropertiesByFamily": {"PRESENTATION": {"FilterName": "MS PowerPoint 2007"}} + }, + { + "name": "Microsoft PowerPoint 2007 add-in", + "extension": "ppam", + "mediaType": "application/vnd.ms-powerpoint.addin.macroEnabled.12", + "inputFamily": "PRESENTATION", + "storePropertiesByFamily": {"PRESENTATION": {"FilterName": "MS PowerPoint 2007"}} + }, + { + "name": "Microsoft PowerPoint 2007 slide", + "extension": "sldx", + "mediaType": "application/vnd.openxmlformats-officedocument.presentationml.slide", + "inputFamily": "PRESENTATION", + "storePropertiesByFamily": {"PRESENTATION": {"FilterName": "MS PowerPoint 2007"}} + }, + { + "name": "Microsoft PowerPoint 2007 macro-enabled slide", + "extension": "sldm", + "mediaType": "application/vnd.ms-powerpoint.slideshow.macroEnabled.12", + "inputFamily": "PRESENTATION", + "storePropertiesByFamily": {"PRESENTATION": {"FilterName": "MS PowerPoint 2007"}} + }, + { + "name": "Microsoft Visio", + "extension": "vsd", + "mediaType": "application/vnd.visio", + "inputFamily": "DRAWING", + "storePropertiesByFamily": {"DRAWING": {"FilterName": "MS Visio"}} + }, + { + "name": "Microsoft Visio 2013", + "extension": "vsdx", + "mediaType": "application/vnd.visio2013", + "inputFamily": "DRAWING", + "storePropertiesByFamily": {"DRAWING": {"FilterName": "MS Visio 2013"}} + }, + { + "name": "OpenDocument Drawing", + "extension": "odg", + "mediaType": "application/vnd.oasis.opendocument.graphics", + "inputFamily": "DRAWING", + "storePropertiesByFamily": {"DRAWING": {"FilterName": "draw8"}} + }, + { + "name": "Scalable Vector Graphics", + "extension": "svg", + "mediaType": "image/svg+xml", + "storePropertiesByFamily": {"DRAWING": {"FilterName": "draw_svg_Export"}} + } +] diff --git a/src/main/resources/alfresco/mimetype/openoffice-document-formats.xml b/src/main/resources/alfresco/mimetype/openoffice-document-formats.xml deleted file mode 100644 index fa2494df45..0000000000 --- a/src/main/resources/alfresco/mimetype/openoffice-document-formats.xml +++ /dev/null @@ -1,426 +0,0 @@ - - - - - - Portable Document Format - application/pdf - pdf - - Presentationimpress_pdf_Export - Spreadsheetcalc_pdf_Export - Textwriter_pdf_Export - - - - Macromedia Flash - application/x-shockwave-flash - swf - - Presentationimpress_flash_Export - - - - - Html - Text - text/html - html - - Presentationimpress_html_Export - SpreadsheetHTML (StarCalc) - TextHTML (StarWriter) - - - - - - OpenDocument Text - Text - application/vnd.oasis.opendocument.text - odt - - Textwriter8 - - - - OpenDocument Text Template - Text - application/vnd.oasis.opendocument.text-template - ott - - Textwriter8 - - - - OpenOffice.org 1.0 Text Document - Text - application/vnd.sun.xml.writer - sxw - - TextStarOffice XML (Writer) - - - - OpenOffice.org 1.0 Text Document Template - Text - application/vnd.sun.xml.writer.template - stw - - TextStarOffice XML (Writer) - - - - Microsoft Word - Text - application/msword - doc - - TextMS Word 97 - - - - Microsoft Word 2007 - Text - application/vnd.openxmlformats-officedocument.wordprocessingml.document - docx - - TextMS Word 2007 - - - - Microsoft Word 2007 macro-enabled document - Text - application/vnd.ms-word.document.macroEnabled.12 - docm - - TextMS Word 2007 - - - - Microsoft Word template 2007 - Text - application/vnd.openxmlformats-officedocument.wordprocessingml.template - dotx - - TextMS Word 2007 - - - - Microsoft Word 2007 macro-enabled document template - Text - application/vnd.ms-word.template.macroEnabled.12 - dotm - - TextMS Word 2007 - - - - WordPerfect - Text - application/wordperfect - wpd - - TextWordPerfect - - - - Rich Text Format - Text - text/rtf - rtf - - TextRich Text Format - - - - Plain Text - Text - text/plain - txt - - TextText - - - - - - OpenDocument Spreadsheet - Spreadsheet - application/vnd.oasis.opendocument.spreadsheet - ods - - Spreadsheetcalc8 - - - - OpenDocument Spreadsheet Template - Spreadsheet - application/vnd.oasis.opendocument.spreadsheet-template - ots - - Spreadsheetcalc8 - - - - OpenOffice.org 1.0 Spreadsheet - Spreadsheet - application/vnd.sun.xml.calc - sxc - - SpreadsheetStarOffice XML (Calc) - - - - OpenOffice.org 1.0 Spreadsheet Template - Spreadsheet - application/vnd.sun.xml.calc.template - stc - - SpreadsheetStarOffice XML (Calc) - - - - - Microsoft Excel - Spreadsheet - application/vnd.ms-excel - xls - - SpreadsheetMS Excel 97 - - - - Microsoft Excel 2007 - Spreadsheet - application/vnd.openxmlformats-officedocument.spreadsheetml.sheet - xlsx - - SpreadsheetMS Excel 2007 - - - - Microsoft Excel template 2007 - Spreadsheet - application/vnd.openxmlformats-officedocument.spreadsheetml.template - xltx - - SpreadsheetMS Excel 2007 - - - - Microsoft Excel 2007 macro-enabled workbook - Spreadsheet - application/vnd.ms-excel.sheet.macroEnabled.12 - xlsm - - SpreadsheetMS Excel 2007 - - - - Microsoft Excel 2007 macro-enabled workbook template - Spreadsheet - application/vnd.ms-excel.template.macroEnabled.12 - xltm - - SpreadsheetMS Excel 2007 - - - - - - Microsoft Excel 2007 binary workbook - Spreadsheet - application/vnd.ms-excel.sheet.binary.macroEnabled.12 - xlsb - - SpreadsheetMS Excel 2007 - - - - - - - - - - OpenDocument Presentation - Presentation - application/vnd.oasis.opendocument.presentation - odp - - Presentationimpress8 - - - - OpenDocument Presentation Template - Presentation - application/vnd.oasis.opendocument.presentation-template - otp - - Presentationimpress8 - - - - OpenOffice.org 1.0 Presentation - Presentation - application/vnd.sun.xml.impress - sxi - - PresentationStarOffice XML (Impress) - - - - OpenOffice.org 1.0 Presentation Template - Presentation - application/vnd.sun.xml.impress.template - sti - - PresentationStarOffice XML (Impress) - - - - Microsoft PowerPoint - Presentation - application/vnd.ms-powerpoint - ppt - - PresentationMS PowerPoint 97 - - - - Microsoft PowerPoint 2007 presentation - Presentation - application/vnd.openxmlformats-officedocument.presentationml.presentation - pptx - - PresentationMS PowerPoint 2007 - - - - Microsoft owerPoint 2007 macro-enabled presentation - Presentation - application/vnd.ms-powerpoint.presentation.macroEnabled.12 - pptm - - PresentationMS PowerPoint 2007 - - - - - - - - Microsoft PowerPoint 2007 template - Presentation - application/vnd.openxmlformats-officedocument.presentationml.template - potx - - PresentationMS PowerPoint 2007 - - - - Microsoft PowerPoint 2007 macro-enabled presentation template - Presentation - application/vnd.ms-powerpoint.template.macroEnabled.12 - potm - - PresentationMS PowerPoint 2007 - - - - Microsoft PowerPoint 2007 add-in - Presentation - application/vnd.ms-powerpoint.addin.macroEnabled.12 - ppam - - PresentationMS PowerPoint 2007 - - - - Microsoft PowerPoint 2007 slide - Presentation - application/vnd.openxmlformats-officedocument.presentationml.slide - sldx - - PresentationMS PowerPoint 2007 - - - - Microsoft PowerPoint 2007 macro-enabled slide - Presentation - application/vnd.ms-powerpoint.slideshow.macroEnabled.12 - sldm - - PresentationMS PowerPoint 2007 - - - - Microsoft Visio - Presentation - application/vnd.visio - vsd - - PresentationMS Visio - - - - Microsoft Visio 2013 - Presentation - application/vnd.visio2013 - vsdx - - PresentationMS Visio - - - - OpenDocument Drawing - Presentation - application/vnd.oasis.opendocument.graphics - odg - - Presentationdraw8 - - - - diff --git a/src/main/resources/alfresco/repository.properties b/src/main/resources/alfresco/repository.properties index 15ddc2cb57..9d0a0f279e 100644 --- a/src/main/resources/alfresco/repository.properties +++ b/src/main/resources/alfresco/repository.properties @@ -161,9 +161,6 @@ shutdown.backstop.enabled=false # 0 prevents further logins, including the ability to enter single-user mode server.maxusers=-1 -# The Cron expression controlling the frequency with which the OpenOffice connection is tested -openOffice.test.cronExpression=0 * * * * ? - # # Disable all shared caches (mutable and immutable) # These properties are used for diagnostic purposes @@ -592,8 +589,6 @@ monitor.rmi.service.enabled=false mbean.server.locateExistingServerIfPossible=true # External executable locations -ooo.exe=soffice -ooo.user=${dir.root}/oouser img.root=./ImageMagick img.dyn=${img.root}/lib img.exe=${img.root}/bin/convert diff --git a/src/main/resources/alfresco/subsystems/OOoDirect/default/openoffice-transform-context.xml b/src/main/resources/alfresco/subsystems/OOoDirect/default/openoffice-transform-context.xml deleted file mode 100644 index d9a2c5db9a..0000000000 --- a/src/main/resources/alfresco/subsystems/OOoDirect/default/openoffice-transform-context.xml +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - false - - - - - - - - startOpenOffice - - - - - - - - - - - startListener - - - - - - ${ooo.enabled} - - - ${ooo.host} - - - ${ooo.port} - - - - - - - - - - - ${ooo.exe} - - - ${ooo.port} - - - ${ooo.user} - - - - - false - - - 2 - - - - - ${ooo.exe} - - - - - - - - - - - - - - - - - - - false - - - - - - org.alfresco.util.OpenOfficeConnectionTester$OpenOfficeConnectionTesterJob - - - - - - - - - - - - - - - - - - - ${openOffice.test.cronExpression} - - - - - - ${system.cronJob.startDelayMinutes} - - - - - - - - - - - - - - - - - - - - - classpath:alfresco/mimetype/openoffice-document-formats.xml - - - - - - - \ No newline at end of file diff --git a/src/main/resources/alfresco/subsystems/OOoDirect/default/openoffice-transform.properties b/src/main/resources/alfresco/subsystems/OOoDirect/default/openoffice-transform.properties deleted file mode 100644 index d57e782398..0000000000 --- a/src/main/resources/alfresco/subsystems/OOoDirect/default/openoffice-transform.properties +++ /dev/null @@ -1,8 +0,0 @@ -# External executable locations -ooo.exe=soffice - -# This property determines whether the OOoDirect services are available. -# Allowed values: "true" or "false" -ooo.enabled=true -ooo.host=localhost -ooo.port=8100 \ No newline at end of file diff --git a/src/main/resources/alfresco/subsystems/OOoJodconverter/default/jodconverter-context.xml b/src/main/resources/alfresco/subsystems/OOoJodconverter/default/jodconverter-context.xml new file mode 100644 index 0000000000..09ae370b76 --- /dev/null +++ b/src/main/resources/alfresco/subsystems/OOoJodconverter/default/jodconverter-context.xml @@ -0,0 +1,64 @@ + + + + + + ${jodconverter.officeHome} + + + ${jodconverter.maxTasksPerProcess} + + + ${jodconverter.taskExecutionTimeout} + + + ${jodconverter.taskQueueTimeout} + + + ${jodconverter.connectTimeout} + + + ${jodconverter.portNumbers} + + + ${jodconverter.templateProfileDir} + + + ${jodconverter.enabled} + + + ${ooo.exe} + + + ${ooo.port} + + + ${ooo.enabled} + + + + + + + + + + + + + + + + + + + + + classpath:alfresco/mimetype/jodconverter-document-formats.json + + + + + + + diff --git a/src/main/resources/alfresco/subsystems/OOoJodconverter/default/jodconverter.properties b/src/main/resources/alfresco/subsystems/OOoJodconverter/default/jodconverter.properties new file mode 100644 index 0000000000..ba96d21ad2 --- /dev/null +++ b/src/main/resources/alfresco/subsystems/OOoJodconverter/default/jodconverter.properties @@ -0,0 +1,47 @@ +# External executable locations + +# This property determines whether the jodConverter services are enabled. +# Allowed values are 'true' or 'false'. +jodconverter.enabled=true + +# The property jodconverter.officeHome is used to locate LibreOffice's 'soffice.bin' executable file. +# +# For Mac OS X this should be the directory that contains "MacOS/soffice.bin" +# So it should be like: /Applications/OpenOffice.org.app/Contents +# +# For other OSes this should be the directory that contains "program/soffice.bin" +# Debian/Ubuntu it should be like: /usr/lib64/libreoffice +# Fedora it should be like: /opt/openoffice.org3 +# Windows it should be like: C:/Alfresco/libreoffice +jodconverter.officeHome=/usr/lib64/libreoffice + +# 1 or more unique port numbers can be specified. They must be comma-separated if there are more than +# one, like so: +#jodconverter.portNumbers=2002, 2003, 2004 +# Note that it is by specifying multiple port numbers that one can create a pool of n instances of OOo +# These port numbers must be available for use. +jodconverter.portNumbers=2022 + +# The maximum number of OOo-related tasks to perform before a process restart +jodconverter.maxTasksPerProcess=200 + +# timeouts are in milliseconds +jodconverter.taskExecutionTimeout=120000 +jodconverter.taskQueueTimeout=30000 + +jodconverter.connectTimeout=25000 + +# OpenOffice user template profile to be used by the JOD started OpenOffice process. +# Among other settings, the profile contains values set in Tools|Options via the UI +# This includes the temporary directory: Tools|Options|openOffice.org|Temporary Files +# +# If blank, a default profile is created. The user profile is recreated on each restart from the template. +# May be set to an existing user's profile such as: C:\Users\\AppData\Roaming\OpenOffice.org\3 + +jodconverter.templateProfileDir= + +# Default values for the old ooo.direct transformer that was used by Community. Now replaced by jodconverter. +# However we don't want to force community users to change all their configuration. +ooo.exe= +ooo.enabled= +ooo.port= \ No newline at end of file diff --git a/src/main/resources/alfresco/subsystems/Transformers/default/transformers.properties b/src/main/resources/alfresco/subsystems/Transformers/default/transformers.properties index 4e8cbd65ea..929acd6f98 100644 --- a/src/main/resources/alfresco/subsystems/Transformers/default/transformers.properties +++ b/src/main/resources/alfresco/subsystems/Transformers/default/transformers.properties @@ -158,8 +158,8 @@ content.transformer.complex.PDF.Image.extensions.ai.gif.priority=50 content.transformer.complex.PDF.Image.extensions.pdf.jpg.priority=50 content.transformer.complex.PDF.Image.extensions.pdf.gif.priority=50 -# JodConverter (OpenOffice should be the same) -# -------------------------------------------- +# JodConverter +# ------------ content.transformer.JodConverter.edition=Enterprise content.transformer.JodConverter.priority=110 content.transformer.JodConverter.extensions.*.xlsm.supported=false @@ -254,99 +254,6 @@ content.transformer.complex.JodConverter.PdfBox.extensions.ppsx.txt.supported=fa content.transformer.complex.JodConverter.PdfBox.extensions.xlsb.txt.maxSourceSizeKBytes=1024 content.transformer.complex.JodConverter.PdfBox.extensions.potm.txt.maxSourceSizeKBytes=1024 - -# OpenOffice (JodConverter should be the same) -# -------------------------------------------- -content.transformer.OpenOffice.priority=110 -content.transformer.OpenOffice.extensions.*.xlsm.supported=false -content.transformer.OpenOffice.extensions.*.pptm.supported=false -content.transformer.OpenOffice.extensions.*.sldm.supported=false -content.transformer.OpenOffice.extensions.*.xltx.supported=false -content.transformer.OpenOffice.extensions.*.docx.supported=false -content.transformer.OpenOffice.extensions.*.potx.supported=false -content.transformer.OpenOffice.extensions.*.xlsx.supported=false -content.transformer.OpenOffice.extensions.*.pptx.supported=false -content.transformer.OpenOffice.extensions.*.xlam.supported=false -content.transformer.OpenOffice.extensions.*.docm.supported=false -content.transformer.OpenOffice.extensions.*.xltm.supported=false -content.transformer.OpenOffice.extensions.*.dotx.supported=false -content.transformer.OpenOffice.extensions.*.xlsb.supported=false -content.transformer.OpenOffice.extensions.*.sldx.supported=false -content.transformer.OpenOffice.extensions.*.ppsm.supported=false -content.transformer.OpenOffice.extensions.*.txt.supported=false -content.transformer.OpenOffice.extensions.*.potm.supported=false -content.transformer.OpenOffice.extensions.*.ppam.supported=false -content.transformer.OpenOffice.extensions.*.dotm.supported=false -content.transformer.OpenOffice.extensions.*.ppsx.supported=false -content.transformer.OpenOffice.extensions.html.pdf.supported=false -content.transformer.OpenOffice.extensions.xlsm.pdf.maxSourceSizeKBytes=1536 -content.transformer.OpenOffice.extensions.pptm.pdf.maxSourceSizeKBytes=4096 -content.transformer.OpenOffice.extensions.xls.pdf.maxSourceSizeKBytes=10240 -content.transformer.OpenOffice.extensions.sldm.pdf.maxSourceSizeKBytes=4096 -content.transformer.OpenOffice.extensions.xltx.pdf.maxSourceSizeKBytes=1536 -content.transformer.OpenOffice.extensions.potx.pdf.maxSourceSizeKBytes=4096 -content.transformer.OpenOffice.extensions.docx.pdf.maxSourceSizeKBytes=768 -content.transformer.OpenOffice.extensions.xlsx.pdf.maxSourceSizeKBytes=1536 -content.transformer.OpenOffice.extensions.pptx.pdf.maxSourceSizeKBytes=4096 -content.transformer.OpenOffice.extensions.xlam.pdf.maxSourceSizeKBytes=1536 -content.transformer.OpenOffice.extensions.ppt.pdf.maxSourceSizeKBytes=6144 -content.transformer.OpenOffice.extensions.docm.pdf.maxSourceSizeKBytes=768 -content.transformer.OpenOffice.extensions.xltm.pdf.maxSourceSizeKBytes=1536 -content.transformer.OpenOffice.extensions.dotx.pdf.maxSourceSizeKBytes=768 -content.transformer.OpenOffice.extensions.xlsb.pdf.maxSourceSizeKBytes=1536 -content.transformer.OpenOffice.extensions.sldx.pdf.maxSourceSizeKBytes=4096 -content.transformer.OpenOffice.extensions.ppsm.pdf.maxSourceSizeKBytes=4096 -content.transformer.OpenOffice.extensions.potm.pdf.maxSourceSizeKBytes=4096 -content.transformer.OpenOffice.extensions.txt.pdf.maxSourceSizeKBytes=5120 -content.transformer.OpenOffice.extensions.ppam.pdf.maxSourceSizeKBytes=4096 -content.transformer.OpenOffice.extensions.dotm.pdf.maxSourceSizeKBytes=768 -content.transformer.OpenOffice.extensions.doc.pdf.maxSourceSizeKBytes=10240 -content.transformer.OpenOffice.extensions.vsd.pdf.maxSourceSizeKBytes=4096 -content.transformer.OpenOffice.extensions.vsdx.pdf.maxSourceSizeKBytes=4096 -content.transformer.OpenOffice.extensions.ppsx.pdf.maxSourceSizeKBytes=4096 - -content.transformer.OpenOffice.Html2Pdf.pipeline=OpenOffice|odt|OpenOffice -content.transformer.OpenOffice.Html2Pdf.priority=200 -content.transformer.OpenOffice.Html2Pdf.extensions.html.pdf.supported=true -content.transformer.OpenOffice.Html2Pdf.extensions.html.pdf.priority=50 - -# This transformer exists because OpenOffice and LibreOffice have a problem -# going directly from HTML to PDF. Going via ODT appears a much better option. -# For example tags hang the soffice process. ALF-14035 -content.transformer.OpenOffice.2Pdf.available=false -content.transformer.OpenOffice.2Pdf.failover=OpenOffice|OpenOffice.Html2Pdf -content.transformer.OpenOffice.2Pdf.priority=150 -content.transformer.OpenOffice.2Pdf.extensions.*.pdf.supported=true - -content.transformer.complex.OpenOffice.Image.pipeline=OpenOffice.2Pdf|pdf|complex.PDF.Image -content.transformer.complex.OpenOffice.Image.priority=250 - -content.transformer.complex.OpenOffice.PdfBox.pipeline=OpenOffice.2Pdf|pdf|PdfBox -content.transformer.complex.OpenOffice.PdfBox.priority=150 -content.transformer.complex.OpenOffice.PdfBox.extensions.xlsm.txt.supported=false -content.transformer.complex.OpenOffice.PdfBox.extensions.pptm.txt.supported=false -content.transformer.complex.OpenOffice.PdfBox.extensions.xls.txt.supported=false -content.transformer.complex.OpenOffice.PdfBox.extensions.sldm.txt.supported=false -content.transformer.complex.OpenOffice.PdfBox.extensions.xltx.txt.supported=false -content.transformer.complex.OpenOffice.PdfBox.extensions.docx.txt.supported=false -content.transformer.complex.OpenOffice.PdfBox.extensions.potx.txt.supported=false -content.transformer.complex.OpenOffice.PdfBox.extensions.xlsx.txt.supported=false -content.transformer.complex.OpenOffice.PdfBox.extensions.pptx.txt.supported=false -content.transformer.complex.OpenOffice.PdfBox.extensions.xlam.txt.supported=false -content.transformer.complex.OpenOffice.PdfBox.extensions.ppt.txt.supported=false -content.transformer.complex.OpenOffice.PdfBox.extensions.docm.txt.supported=false -content.transformer.complex.OpenOffice.PdfBox.extensions.xltm.txt.supported=false -content.transformer.complex.OpenOffice.PdfBox.extensions.dotx.txt.supported=false -content.transformer.complex.OpenOffice.PdfBox.extensions.sldx.txt.supported=false -content.transformer.complex.OpenOffice.PdfBox.extensions.ppsm.txt.supported=false -content.transformer.complex.OpenOffice.PdfBox.extensions.txt.txt.supported=false -content.transformer.complex.OpenOffice.PdfBox.extensions.ppam.txt.supported=false -content.transformer.complex.OpenOffice.PdfBox.extensions.dotm.txt.supported=false -content.transformer.complex.OpenOffice.PdfBox.extensions.doc.txt.supported=false -content.transformer.complex.OpenOffice.PdfBox.extensions.ppsx.txt.supported=false -content.transformer.complex.OpenOffice.PdfBox.extensions.xlsb.txt.maxSourceSizeKBytes=1024 -content.transformer.complex.OpenOffice.PdfBox.extensions.potm.txt.maxSourceSizeKBytes=1024 - # Remote # ------ diff --git a/src/test/java/org/alfresco/MiscContextTestSuite.java b/src/test/java/org/alfresco/MiscContextTestSuite.java index 8461a5410a..3490522283 100644 --- a/src/test/java/org/alfresco/MiscContextTestSuite.java +++ b/src/test/java/org/alfresco/MiscContextTestSuite.java @@ -78,7 +78,7 @@ import org.springframework.context.ApplicationContext; org.alfresco.repo.content.metadata.MP3MetadataExtracterTest.class, org.alfresco.repo.content.metadata.OfficeMetadataExtracterTest.class, org.alfresco.repo.content.metadata.OpenDocumentMetadataExtracterTest.class, - org.alfresco.repo.content.metadata.OpenOfficeMetadataExtracterTest.class, + org.alfresco.repo.content.metadata.JodMetadataExtractorOOoTest.class, org.alfresco.repo.content.metadata.PdfBoxMetadataExtracterTest.class, org.alfresco.repo.content.metadata.ConcurrencyPdfBoxMetadataExtracterTest.class, org.alfresco.repo.content.metadata.PoiMetadataExtracterTest.class, diff --git a/src/test/java/org/alfresco/repo/content/AbstractJodConverterBasedTest.java b/src/test/java/org/alfresco/repo/content/AbstractJodConverterBasedTest.java new file mode 100644 index 0000000000..da51bfc819 --- /dev/null +++ b/src/test/java/org/alfresco/repo/content/AbstractJodConverterBasedTest.java @@ -0,0 +1,233 @@ +/* + * #%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 . + * #L% + */ +package org.alfresco.repo.content; + +import java.io.File; +import java.io.Serializable; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.Map; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.repo.content.transform.AbstractContentTransformerTest; +import org.alfresco.repo.content.transform.ContentTransformer; +import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory; +import org.alfresco.repo.model.Repository; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import org.alfresco.service.ServiceRegistry; +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.cmr.repository.TransformationOptions; +import org.alfresco.service.cmr.thumbnail.ThumbnailService; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.alfresco.service.transaction.TransactionService; +import org.alfresco.util.ApplicationContextHelper; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.springframework.context.ApplicationContext; + +/** + * + * @author Neil McErlean + * @since 3.3 + */ +@Ignore("This is an abstract class so don't instaniate it or run it in Junit") +public abstract class AbstractJodConverterBasedTest +{ + private static Log log = LogFactory.getLog(AbstractJodConverterBasedTest.class); + + protected static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext(); + + protected static ServiceRegistry serviceRegistry; + protected static TransactionService transactionService; + protected static NodeService nodeService; + protected static ContentService contentService; + protected static ThumbnailService thumbnailService; + private static Repository repositoryHelper; + + private static ChildApplicationContextFactory oooJodcSubsystem; + + protected NodeRef contentNodeRef; + protected LinkedList nodesToDeleteAfterTest = new LinkedList(); + + + /** + * This test relies upon customised OpenOffice.org subsystems being available. + * The OOoDirect subsystem (usually enabled by default) is disabled and the + * OOoJodconverter subsystem (usually disabled by default) is enabled. + * @throws Exception + */ + @BeforeClass + public static void initServicesAndRestartOOoSubsystems() throws Exception + { + if (log.isDebugEnabled()) + { + log.debug("initServicesAndRestartOOoSubsystems"); + } + + repositoryHelper = (Repository) ctx.getBean("repositoryHelper"); + serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY); + contentService = serviceRegistry.getContentService(); + nodeService = serviceRegistry.getNodeService(); + thumbnailService = serviceRegistry.getThumbnailService(); + transactionService = serviceRegistry.getTransactionService(); + + AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName()); + + oooJodcSubsystem = (ChildApplicationContextFactory) ctx.getBean("OOoJodconverter"); + + // Stop the OOoJodconverter subsystem and restart it with test settings i.e. enabled. + // Also a pool of 3 JodConverter instances, just for fun. + if (log.isDebugEnabled()) + { + log.debug("Enabling OOoJodconverter"); + } + oooJodcSubsystem.stop(); + oooJodcSubsystem.setProperty("jodconverter.enabled", "true"); + oooJodcSubsystem.setProperty("jodconverter.portNumbers", "2022, 2023, 2024"); + oooJodcSubsystem.start(); + } + + /** + * Returns true if OpenOffice-based transformations are currently known to + * be available, else false. + */ + protected boolean isOpenOfficeAvailable() + { + ContentTransformer transformer = contentService.getTransformer(null, MimetypeMap.MIMETYPE_WORD, -1, MimetypeMap.MIMETYPE_PDF, new TransformationOptions()); + + // A transformer may not be returned here if it is unavailable. + if (transformer == null) + { + return false; + } + + // Maybe it's non-null, but not available. + boolean isTransformable = transformer.isTransformable(MimetypeMap.MIMETYPE_WORD, -1, MimetypeMap.MIMETYPE_PDF, null); + return isTransformable; + } + + @Before + public void createTemporaryNodeRefs() throws Exception + { + // Create a content node which will serve as test data for our transformations. + RetryingTransactionCallback makeNodeCallback = new RetryingTransactionCallback() + { + public NodeRef execute() throws Throwable + { + if (log.isDebugEnabled()) + { + log.debug("Creating temporary NodeRefs for testing."); + } + + final NodeRef companyHome = repositoryHelper.getCompanyHome(); + // Create a folder + Map folderProps = new HashMap(); + folderProps.put(ContentModel.PROP_NAME, this.getClass().getSimpleName() + System.currentTimeMillis()); + + NodeRef folderNodeRef = nodeService.createNode(companyHome, ContentModel.ASSOC_CONTAINS, + ContentModel.ASSOC_CONTAINS, ContentModel.TYPE_FOLDER, folderProps).getChildRef(); + nodesToDeleteAfterTest.add(folderNodeRef); + + // Add some content. + File origFile = AbstractContentTransformerTest.loadQuickTestFile("doc"); + + Map props = new HashMap(); + props.put(ContentModel.PROP_NAME, "original." + "doc"); + NodeRef node = nodeService.createNode( + folderNodeRef, + ContentModel.ASSOC_CONTAINS, + QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "original.doc"), + ContentModel.TYPE_CONTENT, + props).getChildRef(); + + ContentWriter writer = contentService.getWriter(node, ContentModel.PROP_CONTENT, true); + writer.setMimetype(MimetypeMap.MIMETYPE_WORD); + writer.setEncoding("UTF-8"); + writer.putContent(origFile); + + return node; + } + }; + contentNodeRef = transactionService.getRetryingTransactionHelper().doInTransaction(makeNodeCallback); + this.nodesToDeleteAfterTest.add(contentNodeRef); + } + + @After + public void deleteTemporaryNodeRefs() + { + // Tidy up the test nodes we created + RetryingTransactionCallback deleteNodeCallback = new RetryingTransactionCallback() + { + public Void execute() throws Throwable + { + // Delete them in reverse order. + for (Iterator iter = nodesToDeleteAfterTest.descendingIterator(); iter.hasNext(); ) + { + NodeRef nextNodeToDelete = iter.next(); + + if (nodeService.exists(nextNodeToDelete)) + { + if (log.isDebugEnabled()) + { + log.debug("Deleting temporary node " + nextNodeToDelete); + } + nodeService.deleteNode(nextNodeToDelete); + } + } + + return null; + } + }; + transactionService.getRetryingTransactionHelper().doInTransaction(deleteNodeCallback); + } + + @AfterClass + public static void stopOOoSubsystems() throws Exception + { + // Put the OOoJodconverter subsystem back to its install settings (disabled). + if (log.isDebugEnabled()) + { + log.debug("Disabling OOoJodconverter"); + } + oooJodcSubsystem.stop(); + oooJodcSubsystem.setProperty("jodconverter.enabled", "false"); + oooJodcSubsystem.start(); + + oooJodcSubsystem.stop(); + } +} diff --git a/src/test/java/org/alfresco/repo/content/JodConverterSharedInstanceTest.java b/src/test/java/org/alfresco/repo/content/JodConverterSharedInstanceTest.java new file mode 100644 index 0000000000..f4d7f46bdf --- /dev/null +++ b/src/test/java/org/alfresco/repo/content/JodConverterSharedInstanceTest.java @@ -0,0 +1,244 @@ +/* + * #%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 . + * #L% + */ +package org.alfresco.repo.content; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.MockitoAnnotations; + +import java.io.File; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +/** + * Tests methods added to JodConverterSharedInstance that try to use the replaced oooDirect settings. + * @author Alan Davis + */ +public class JodConverterSharedInstanceTest +{ + public static final String LIBREOFFICE = "libreoffice"; + public static final String PROGRAM = "program"; + public static final String ELSEWHERE = "elsewhere"; + public static final String SOFFICE_BIN = "soffice.bin"; + public static final String SOFFICE_EXE = "soffice.exe"; + + private static final File OFFICE_HOME_DIR = new File(LIBREOFFICE); + private static final File PROGRAM_DIR = new File(OFFICE_HOME_DIR, PROGRAM); + private static final File ELSEWHERE_DIR = new File(OFFICE_HOME_DIR, ELSEWHERE); + + private static final String OFFICE_HOME = OFFICE_HOME_DIR.getPath(); + private static final String PROGRAM_BIN = new File( PROGRAM_DIR, SOFFICE_BIN).getPath(); + private static final String PROGRAM_EXE = new File( PROGRAM_DIR, SOFFICE_EXE).getPath(); + private static final String ELSEWHERE_BIN = new File( ELSEWHERE_DIR, SOFFICE_BIN).getPath(); + private static final String NO_OFFICE_HOME_BIN = new File(new File(PROGRAM), SOFFICE_BIN).getPath(); + private static final String JUST_SOFFICE_BIN = new File( SOFFICE_BIN).getPath(); + + + private JodConverterSharedInstance instance; + + @Before + public void setUp() throws Exception + { + MockitoAnnotations.initMocks(this); + instance = new JodConverterSharedInstance(); + } + + @Test + public void setupTest() + { + String SLASH = File.separator; + assertEquals(LIBREOFFICE, OFFICE_HOME); + assertEquals(LIBREOFFICE + SLASH + PROGRAM + SLASH + SOFFICE_EXE, PROGRAM_EXE); + assertEquals(LIBREOFFICE + SLASH + PROGRAM + SLASH + SOFFICE_BIN, PROGRAM_BIN); + assertEquals(LIBREOFFICE + SLASH + ELSEWHERE + SLASH + SOFFICE_BIN, ELSEWHERE_BIN); + assertEquals( PROGRAM + SLASH + SOFFICE_BIN, NO_OFFICE_HOME_BIN); + assertEquals( SOFFICE_BIN, JUST_SOFFICE_BIN); + assertNotEquals(PROGRAM_BIN, PROGRAM_EXE); + } + + @Test + public void officeHomeTest() + { + // Only jodconverter.officehome + instance.setOfficeHome(OFFICE_HOME); + instance.setDeprecatedOooExe(null); + assertEquals(OFFICE_HOME, instance.getOfficeHome()); + + // Use ooo.exe + instance.setOfficeHome(null); + instance.setDeprecatedOooExe(PROGRAM_BIN); + assertEquals(OFFICE_HOME, instance.getOfficeHome()); + + // jodconverter.officehome wins + instance.setOfficeHome(OFFICE_HOME); + instance.setDeprecatedOooExe(PROGRAM_EXE); + assertEquals(OFFICE_HOME, instance.getOfficeHome()); + + // ooo.exe has no parent + instance.setOfficeHome(null); + instance.setDeprecatedOooExe(JUST_SOFFICE_BIN); + assertEquals("", instance.getOfficeHome()); + + // ooo.exe parent is not "program" + instance.setOfficeHome(null); + instance.setDeprecatedOooExe(ELSEWHERE_BIN); + assertEquals("", instance.getOfficeHome()); + + // ooo.exe has a parent "program" directory but no grandparent + instance.setOfficeHome(null); + instance.setDeprecatedOooExe(NO_OFFICE_HOME_BIN); + assertEquals("", instance.getOfficeHome()); + } + + @Test + public void enabledTest() + { + // If ooo.enabled is true the JodConverter will be enabled, otherwise 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. + + // Only jodconverter.enabled + instance = new JodConverterSharedInstance(); + instance.setEnabled("true"); + instance.setDeprecatedOooEnabled(null); + assertTrue(instance.isEnabled()); + + instance = new JodConverterSharedInstance(); + instance.setEnabled("true"); + assertTrue(instance.isEnabled()); + + instance = new JodConverterSharedInstance(); + instance.setEnabled("false"); + instance.setDeprecatedOooEnabled(null); + assertFalse(instance.isEnabled()); + + instance = new JodConverterSharedInstance(); + instance.setEnabled("false"); + assertFalse(instance.isEnabled()); + + instance = new JodConverterSharedInstance(); + instance.setEnabled("any value other than true"); + instance.setDeprecatedOooEnabled(null); + assertFalse(instance.isEnabled()); + + instance = new JodConverterSharedInstance(); + instance.setEnabled(""); + instance.setDeprecatedOooEnabled(null); + assertFalse(instance.isEnabled()); + + instance = new JodConverterSharedInstance(); + instance.setEnabled(null); + instance.setDeprecatedOooEnabled(null); + assertFalse(instance.isEnabled()); + + // Use ooo.enabled + instance = new JodConverterSharedInstance(); + instance.setEnabled(null); + instance.setDeprecatedOooEnabled("true"); + assertTrue(instance.isEnabled()); + + instance = new JodConverterSharedInstance(); + instance.setEnabled(null); + instance.setDeprecatedOooEnabled("false"); + assertFalse(instance.isEnabled()); + + instance = new JodConverterSharedInstance(); + instance.setDeprecatedOooEnabled("true"); + assertTrue(instance.isEnabled()); + + instance = new JodConverterSharedInstance(); + instance.setDeprecatedOooEnabled("false"); + assertFalse(instance.isEnabled()); + + // Check jodconverter.enabled is used if ooo.enabled is false - Original Enterprise setup + instance = new JodConverterSharedInstance(); + instance.setEnabled("true"); + instance.setDeprecatedOooEnabled("false"); + assertTrue(instance.isEnabled()); + + instance = new JodConverterSharedInstance(); + instance.setEnabled("false"); + instance.setDeprecatedOooEnabled("false"); + assertFalse(instance.isEnabled()); + + // Check jodconverter.enabled is ignored if ooo.enabled is true - Original Community setup + instance = new JodConverterSharedInstance(); + instance.setEnabled("true"); + instance.setDeprecatedOooEnabled("true"); + assertTrue(instance.isEnabled()); + + instance = new JodConverterSharedInstance(); + instance.setEnabled("false"); + instance.setDeprecatedOooEnabled("true"); + assertTrue(instance.isEnabled()); + + // Check reset of jodconverter.enabled turns off isAvailable + instance = new JodConverterSharedInstance(); + instance.setEnabled("true"); + instance.isAvailable = true; // Normally set to true after running afterPropertiesSet() + instance.setEnabled("true"); + assertTrue(instance.isAvailable); + instance.setEnabled("false"); + assertFalse(instance.isAvailable); + + instance = new JodConverterSharedInstance(); + instance.setEnabled("true"); + instance.setDeprecatedOooEnabled("false"); // Extra line compare with previous + instance.isAvailable = true; + instance.setEnabled("true"); + assertTrue(instance.isAvailable); + instance.setEnabled("false"); + assertFalse(instance.isAvailable); + } + + @Test + public void portNumbersTest() + { + // ooo.port or jodconverter.portNumber is used depending on the setting of enabled properties. + // If jodconverter.enabled is true jodconverter.portNumber is used. + // If jodconverter.enabled is false and ooo.enabled is true ooo.port is used. + // If jodconverter.enabled is false and ooo.enabled is true ooo.port is used. + + // jodconverter.enabled=true use jodconverter.portNumber + instance.setEnabled("true"); + instance.setPortNumbers("8001,8002,8003"); + instance.setDeprecatedOooPort("8001"); + assertArrayEquals(new int[] {8001, 8002, 8003}, instance.getPortNumbers()); + + // jodconverter.enabled=true and ooo.enabled=true use jodconverter.portNumber + instance.setDeprecatedOooEnabled("true"); + assertArrayEquals(new int[] {8001, 8002, 8003}, instance.getPortNumbers()); + + // jodconverter.enabled=false and ooo.enabled=true use ooo.port + instance.setEnabled("false"); + assertArrayEquals(new int[] {8001}, instance.getPortNumbers()); + } +} diff --git a/src/test/java/org/alfresco/repo/content/metadata/AbstractMetadataExtracterTest.java b/src/test/java/org/alfresco/repo/content/metadata/AbstractMetadataExtracterTest.java index f4797ad47f..d034869d21 100644 --- a/src/test/java/org/alfresco/repo/content/metadata/AbstractMetadataExtracterTest.java +++ b/src/test/java/org/alfresco/repo/content/metadata/AbstractMetadataExtracterTest.java @@ -72,8 +72,7 @@ import org.springframework.context.ApplicationContext; /** * @see org.alfresco.repo.content.metadata.MetadataExtracter - * @see org.alfresco.repo.content.metadata.AbstractMetadataExtracter - * + * * @author Jesper Steen Møller */ public abstract class AbstractMetadataExtracterTest extends TestCase diff --git a/src/test/java/org/alfresco/repo/content/metadata/JodMetadataExtractorOOoTest.java b/src/test/java/org/alfresco/repo/content/metadata/JodMetadataExtractorOOoTest.java new file mode 100644 index 0000000000..328598de1e --- /dev/null +++ b/src/test/java/org/alfresco/repo/content/metadata/JodMetadataExtractorOOoTest.java @@ -0,0 +1,140 @@ +/* + * #%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 . + * #L% + */ +package org.alfresco.repo.content.metadata; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.fail; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.Serializable; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.content.AbstractJodConverterBasedTest; +import org.alfresco.model.ContentModel; +import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.repo.content.filestore.FileContentReader; +import org.alfresco.repo.content.metadata.OpenOfficeMetadataWorker; +import org.alfresco.repo.content.transform.AbstractContentTransformerTest; +import org.alfresco.service.cmr.repository.ContentReader; +import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; +import org.alfresco.service.namespace.QName; +import org.junit.Test; + +/** + * + * @author Neil McErlean + * @since 3.2 SP1 + */ +public class JodMetadataExtractorOOoTest extends AbstractJodConverterBasedTest +{ + protected static final String QUICK_TITLE = "The quick brown fox jumps over the lazy dog"; + protected static final String QUICK_DESCRIPTION = "Gym class featuring a brown fox and lazy dog"; + protected static final String QUICK_CREATOR = "Nevin Nollop"; + protected static final String QUICK_CREATOR_EMAIL = "nevin.nollop@alfresco.com"; + protected static final String QUICK_PREVIOUS_AUTHOR = "Derek Hulley"; + + @Test + public void metadataExtractionUsingJodConverter() throws Exception + { + // If OpenOffice is not available then we will ignore this test (by passing it). + // This is because not all the build servers have OOo installed. + if (!isOpenOfficeAvailable()) + { + System.out.println("Did not run " + this.getClass().getSimpleName() + "thumbnailTransformationsUsingJodConverter" + + " because OOo is not available."); + return; + } + + Map properties = extractFromMimetype(); + assertFalse("extractFromMimetype should return at least some properties, none found", properties.isEmpty()); + String mimetype = MimetypeMap.MIMETYPE_WORD; + + // One of Creator or Author + if (properties.containsKey(ContentModel.PROP_CREATOR)) + { + assertEquals("Property " + ContentModel.PROP_CREATOR + + " not found for mimetype " + mimetype, QUICK_CREATOR, + DefaultTypeConverter.INSTANCE.convert(String.class, + properties.get(ContentModel.PROP_CREATOR))); + } else if (properties.containsKey(ContentModel.PROP_AUTHOR)) + { + assertEquals("Property " + ContentModel.PROP_AUTHOR + + " not found for mimetype " + mimetype, QUICK_CREATOR, + DefaultTypeConverter.INSTANCE.convert(String.class, + properties.get(ContentModel.PROP_AUTHOR))); + } else + { + fail("Expected one Property out of " + ContentModel.PROP_CREATOR + + " and " + ContentModel.PROP_AUTHOR + + " but found neither of them."); + } + + // Title and description + assertEquals("Property " + ContentModel.PROP_TITLE + + " not found for mimetype " + mimetype, QUICK_TITLE, + DefaultTypeConverter.INSTANCE.convert(String.class, properties + .get(ContentModel.PROP_TITLE))); + assertEquals("Property " + ContentModel.PROP_DESCRIPTION + + " not found for mimetype " + mimetype, QUICK_DESCRIPTION, + DefaultTypeConverter.INSTANCE.convert(String.class, properties + .get(ContentModel.PROP_DESCRIPTION))); + } + + protected Map extractFromMimetype() throws Exception + { + Map properties = new HashMap(); + + // attempt to get a source file for each mimetype + File sourceFile = AbstractContentTransformerTest.loadQuickTestFile("doc"); + if (sourceFile == null) + { + throw new FileNotFoundException("No quick.doc file found for test"); + } + + // construct a reader onto the source file + ContentReader sourceReader = new FileContentReader(sourceFile); + sourceReader.setMimetype(MimetypeMap.MIMETYPE_WORD); + + OpenOfficeMetadataWorker worker = (OpenOfficeMetadataWorker) ctx.getBean("extracter.worker.JodConverter"); + + Set supportedTypes = new HashSet(); + supportedTypes.add(MimetypeMap.MIMETYPE_WORD); + JodConverterMetadataExtracter extracter = new JodConverterMetadataExtracter(supportedTypes); + extracter.setMimetypeService(serviceRegistry.getMimetypeService()); + extracter.setDictionaryService(serviceRegistry.getDictionaryService()); + extracter.setWorker(worker); + + extracter.init(); + + extracter.extract(sourceReader, properties); + return properties; + } +} diff --git a/src/test/java/org/alfresco/repo/content/metadata/OpenOfficeMetadataExtracterTest.java b/src/test/java/org/alfresco/repo/content/metadata/OpenOfficeMetadataExtracterTest.java deleted file mode 100644 index c96ebcab98..0000000000 --- a/src/test/java/org/alfresco/repo/content/metadata/OpenOfficeMetadataExtracterTest.java +++ /dev/null @@ -1,145 +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 . - * #L% - */ -/* - * Copyright (C) 2005 Jesper Steen Møller - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ -package org.alfresco.repo.content.metadata; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import org.alfresco.repo.content.MimetypeMap; -import org.alfresco.service.namespace.QName; - - -/** - * Note - this test can sometimes fail if run on its own, as there - * can be a race condition with the OO process. Try running it as - * part of a suite if so, that normally seems to fix it! - * - * @author Jesper Steen Møller - */ -public class OpenOfficeMetadataExtracterTest extends AbstractMetadataExtracterTest -{ - private OpenOfficeMetadataExtracter extracter; - - @Override - public void setUp() throws Exception - { - super.setUp(); - - OpenOfficeMetadataWorker worker = (OpenOfficeMetadataWorker) ctx.getBean("extracter.worker.OpenOffice"); - - extracter = new OpenOfficeMetadataExtracter(); - extracter.setMimetypeService(mimetypeMap); - extracter.setDictionaryService(dictionaryService); - extracter.setWorker(worker); - extracter.init(); - } - - /** - * @return Returns the same extracter regardless - it is allowed - */ - protected MetadataExtracter getExtracter() - { - return extracter; - } - - public void testReliability() throws Exception - { - if (!extracter.isConnected()) - { - return; - } - - for (String mimetype : OpenOfficeMetadataExtracter.SUPPORTED_MIMETYPES) - { - assertTrue("Expected above zero reliability", extracter.isSupported(mimetype)); - } - } - - public void testSupportedMimetypes() throws Exception - { - // If this test method is run on its own, then it may run to completion before the OOo connection is reconnected. - // To fully run this test method (with full execution of the various extractions) you need to debug it, - // put a breakpoint below (at extracter.isConnected()) and wait for - // "[alfresco.util.OpenOfficeConnectionTester] The OpenOffice connection was re-established" in the log before - // proceeding. Otherwise the extracter is not "connected" and the tests are short-circuited. - // - // When run on the build server, the timings are such that the OOo connection is available. - if (!extracter.isConnected()) - { - return; - } - for (String mimetype : OpenOfficeMetadataExtracter.SUPPORTED_MIMETYPES) - { - testExtractFromMimetype(mimetype); - } - } - - /** - * Only run the check if we have a connection - * to an OpenOffice instance - */ - protected void testCommonMetadata(String mimetype, - Map properties) { - if(extracter.isConnected()) { - super.testCommonMetadata(mimetype, properties); - } - } - - protected boolean skipAuthorCheck(String mimetype) - { - // The following 'quick' files have no author/creator property and so should not - // have its value checked. - List mimeTypesWithNoAuthor = new ArrayList(); - mimeTypesWithNoAuthor.add(MimetypeMap.MIMETYPE_STAROFFICE5_IMPRESS); - mimeTypesWithNoAuthor.add(MimetypeMap.MIMETYPE_OPENOFFICE1_IMPRESS); - - return mimeTypesWithNoAuthor.contains(mimetype); - } - - - /** Extractor only does the usual basic three properties */ - public void testFileSpecificMetadata(String mimetype, Map properties) {} -} diff --git a/src/test/java/org/alfresco/repo/content/transform/AbstractContentTransformerTest.java b/src/test/java/org/alfresco/repo/content/transform/AbstractContentTransformerTest.java index 7a7f4fd553..e4b1de2065 100644 --- a/src/test/java/org/alfresco/repo/content/transform/AbstractContentTransformerTest.java +++ b/src/test/java/org/alfresco/repo/content/transform/AbstractContentTransformerTest.java @@ -48,6 +48,7 @@ import org.alfresco.service.ServiceRegistry; 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.ApplicationContextHelper; import org.alfresco.util.TempFileProvider; import org.alfresco.util.exec.RuntimeExec; @@ -449,32 +450,8 @@ public abstract class AbstractContentTransformerTest extends TestCase */ protected boolean isOpenOfficeWorkerAvailable() throws InterruptedException { - // workaround for build machines (originally taken from OpenOfficeContentTransformerTest) - ContentTransformerWorker ooWorker = (ContentTransformerWorker) ctx.getBean("transformer.worker.OpenOffice"); - - if (!ooWorker.isAvailable()) - { - // TODO - temporarily attempt to start LibreOffice/OpenOffice (eg. when locally running individual test class &/or method) - // TODO - can we remove this once we have fixed repo startup issue (where LO/OO may not start first time) ? - ChildApplicationContextFactory oooDirectSubsystem = (ChildApplicationContextFactory) ctx.getBean("OOoDirect"); - oooDirectSubsystem.start(); - - Thread.sleep(5000); - - RuntimeExec runtimeExec = (RuntimeExec) oooDirectSubsystem.getApplicationContext().getBean("openOfficeStartupCommand"); - runtimeExec.execute(); - - Thread.sleep(5000); - - if (!ooWorker.isAvailable()) - { - if (failTestIfOOWorkerUnavailable) - { - fail("Failed to run test - ooWorker not available"); - } - return false; - } - } - return true; + ChildApplicationContextFactory jodconverterSubsystem = (ChildApplicationContextFactory) ctx.getBean("OOoJodconverter"); + JodContentTransformer jodContentTransformer = (JodContentTransformer)jodconverterSubsystem.getApplicationContext().getBean("transformer.worker.JodConverter"); + return jodContentTransformer.isAvailable(); } } diff --git a/src/test/java/org/alfresco/repo/content/transform/ComplexContentTransformerTest.java b/src/test/java/org/alfresco/repo/content/transform/ComplexContentTransformerTest.java index b962e30b24..7f049d3aed 100644 --- a/src/test/java/org/alfresco/repo/content/transform/ComplexContentTransformerTest.java +++ b/src/test/java/org/alfresco/repo/content/transform/ComplexContentTransformerTest.java @@ -49,7 +49,7 @@ public class ComplexContentTransformerTest extends AbstractContentTransformerTes { super.setUp(); - ContentTransformer unoTransformer = (ContentTransformer) ctx.getBean("transformer.OpenOffice"); + ContentTransformer unoTransformer = (ContentTransformer) ctx.getBean("transformer.JodConverter"); ContentTransformer pdfBoxTransformer = (ContentTransformer) ctx.getBean("transformer.PdfBox"); // make sure that they are working for this test if (unoTransformer.isTransformable(MimetypeMap.MIMETYPE_PPT, -1, MimetypeMap.MIMETYPE_PDF, new TransformationOptions()) == false) diff --git a/src/test/java/org/alfresco/repo/content/transform/JodContentTransformerOOoTest.java b/src/test/java/org/alfresco/repo/content/transform/JodContentTransformerOOoTest.java new file mode 100644 index 0000000000..0f0ae7f288 --- /dev/null +++ b/src/test/java/org/alfresco/repo/content/transform/JodContentTransformerOOoTest.java @@ -0,0 +1,87 @@ +/* + * #%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 . + * #L% + */ +package org.alfresco.repo.content.transform; + +import static org.junit.Assert.assertNotNull; + +import org.alfresco.repo.content.AbstractJodConverterBasedTest; +import org.alfresco.model.ContentModel; +import org.alfresco.repo.thumbnail.ThumbnailDefinition; +import org.alfresco.repo.thumbnail.ThumbnailRegistry; +import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import org.alfresco.service.cmr.repository.NodeRef; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Test; + +/** + * + * @author Neil McErlean + * @since 3.2 SP1 + */ +public class JodContentTransformerOOoTest extends AbstractJodConverterBasedTest +{ + private static Log log = LogFactory.getLog(JodContentTransformerOOoTest.class); + + /** + * This test method tests the built-in thumbnail transformations - all for a Word source document. + * This will include transformations doc-pdf-png and doc-pdf-swf. ALF-2070 + */ + @Test + public void thumbnailTransformationsUsingJodConverter() + { + // If OpenOffice is not available then we will ignore this test (by passing it). + // This is because not all the build servers have OOo installed. + if (!isOpenOfficeAvailable()) + { + System.out.println("Did not run " + this.getClass().getSimpleName() + ".thumbnailTransformationsUsingJodConverter" + + " because OOo is not available."); + return; + } + + transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() + { + public Void execute() throws Throwable + { + ThumbnailRegistry thumbnailRegistry = thumbnailService.getThumbnailRegistry(); + for (ThumbnailDefinition thumbDef : thumbnailRegistry.getThumbnailDefinitions()) + { + if (log.isDebugEnabled()) + { + log.debug("Testing thumbnail definition " + thumbDef.getName()); + } + + NodeRef thumbnail = thumbnailService.createThumbnail(contentNodeRef, ContentModel.PROP_CONTENT, + thumbDef.getMimetype(), thumbDef.getTransformationOptions(), thumbDef.getName()); + + assertNotNull("Thumbnail was unexpectedly null.", thumbnail); + } + + return null; + } + }); + } +} diff --git a/src/test/java/org/alfresco/repo/content/transform/OpenOfficeContentTransformerTest.java b/src/test/java/org/alfresco/repo/content/transform/OpenOfficeContentTransformerTest.java index df6e1d66f5..439da195cd 100644 --- a/src/test/java/org/alfresco/repo/content/transform/OpenOfficeContentTransformerTest.java +++ b/src/test/java/org/alfresco/repo/content/transform/OpenOfficeContentTransformerTest.java @@ -37,7 +37,8 @@ import org.alfresco.service.cmr.repository.TransformationOptions; import org.alfresco.util.TempFileProvider; /** - * @see org.alfresco.repo.content.transform.OpenOfficeContentTransformerWorker + * We no longer use ooo.direct in Community. This test class now is connnected up to the JODConverter which was moved + * from the Enterprise Edition. * * @author Derek Hulley */ @@ -53,7 +54,7 @@ public class OpenOfficeContentTransformerTest extends AbstractContentTransformer { super.setUp(); - this.worker = (ContentTransformerWorker) ctx.getBean("transformer.worker.OpenOffice"); + this.worker = (ContentTransformerWorker) ctx.getBean("transformer.worker.JodConverter"); transformer = new ProxyContentTransformer(); transformer.setMimetypeService(mimetypeService); transformer.setTransformerDebug(transformerDebug); diff --git a/src/test/java/org/alfresco/repo/content/transform/TransformerPropertiesTest.java b/src/test/java/org/alfresco/repo/content/transform/TransformerPropertiesTest.java new file mode 100644 index 0000000000..937d22a772 --- /dev/null +++ b/src/test/java/org/alfresco/repo/content/transform/TransformerPropertiesTest.java @@ -0,0 +1,90 @@ +/* + * #%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 . + * #L% + */ +package org.alfresco.repo.content.transform; + +import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Matchers; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.Properties; +import java.util.Set; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.when; + +/** + * Test class for TransformerProperties. Currently just that The old oooDirect (OpenOffice) transformer settings + * are aliased to JodConverter settings if they are not set up. + * + * @author Alan Davis + */ +public class TransformerPropertiesTest +{ + @Mock + private ChildApplicationContextFactory subsystem; + + private TransformerProperties transformerProperties; + private Properties globalProperties; + + @Before + public void setUp() throws Exception + { + MockitoAnnotations.initMocks(this); + globalProperties = new Properties(); + transformerProperties = new TransformerProperties(subsystem, globalProperties); + } + + @Test + public void aliasOpenOfficeToJodTest() + { + when(subsystem.getProperty(Matchers.any())).thenReturn(null); + + // Should be picked up as normal + globalProperties.setProperty("content.transformer.complex.JodConverter.Image.priority", "150"); + + // JodConverter value should override the OpenOffice value + globalProperties.setProperty("content.transformer.complex.OpenOffice.Image.extensions.docx.txt.supported", "true"); + globalProperties.setProperty("content.transformer.complex.JodConverter.Image.extensions.docx.txt.supported", "false"); + + // Should be picked up as a JodConverter value + globalProperties.setProperty("content.transformer.complex.OpenOffice.Image.extensions.xlsb.txt.maxSourceSizeKBytes", "1024"); + + Set propertyNames = transformerProperties.getPropertyNames(); + + assertEquals("The combined settings should be seen as only three entries", 3, propertyNames.size()); + assertTrue(propertyNames.contains("content.transformer.complex.JodConverter.Image.priority")); + assertTrue(propertyNames.contains("content.transformer.complex.JodConverter.Image.extensions.docx.txt.supported")); + assertTrue(propertyNames.contains("content.transformer.complex.JodConverter.Image.extensions.xlsb.txt.maxSourceSizeKBytes")); + + assertEquals("150", transformerProperties.getProperty("content.transformer.complex.JodConverter.Image.priority")); + assertEquals("false", transformerProperties.getProperty("content.transformer.complex.JodConverter.Image.extensions.docx.txt.supported")); + assertEquals("1024", transformerProperties.getProperty("content.transformer.complex.JodConverter.Image.extensions.xlsb.txt.maxSourceSizeKBytes")); + } +} diff --git a/src/test/java/org/alfresco/repo/content/transform/TransformerPropertySetterTest.java b/src/test/java/org/alfresco/repo/content/transform/TransformerPropertySetterTest.java index 330f5f04eb..296eb0bc22 100644 --- a/src/test/java/org/alfresco/repo/content/transform/TransformerPropertySetterTest.java +++ b/src/test/java/org/alfresco/repo/content/transform/TransformerPropertySetterTest.java @@ -1,28 +1,28 @@ -/* - * #%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 . - * #L% - */ +/* + * #%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 . + * #L% + */ package org.alfresco.repo.content.transform; import static org.junit.Assert.assertEquals; @@ -150,58 +150,58 @@ public class TransformerPropertySetterTest verify(transformerProperties).setProperties(expectedProperties("Transformer.LOG.entries", "12")); } - @Test - public void debugLogSizeTest() - { - setter.setProperties( - "transformer.log.entries=12\n" + - "transformer.debug.entries=-1"); - - verify(transformerProperties).setProperties(expectedProperties( - "transformer.debug.entries", "-1", - "transformer.log.entries", "12")); - } - - @Test - public void mimetypeListTest() - { - setter.setProperties( - "transformer.strict.mimetype.check.whitelist.mimetypes=image/png;application/pdf"); - - verify(transformerProperties).setProperties(expectedProperties( - "transformer.strict.mimetype.check.whitelist.mimetypes", "image/png;application/pdf")); - } - - public void mimetypeListBlankTest() - { - setter.setProperties( - "transformer.strict.mimetype.check.whitelist.mimetypes="); - - verify(transformerProperties).setProperties(expectedProperties( - "transformer.strict.mimetype.check.whitelist.mimetypes", "")); - } - - @Test(expected=IllegalArgumentException.class) - public void mimetypeListUnevenTest() - { - setter.setProperties( - "transformer.strict.mimetype.check.whitelist.mimetypes=image/png"); - } - - @Test(expected=IllegalArgumentException.class) - public void mimetypeListBadDeclaredTypeTest() - { - setter.setProperties( - "transformer.strict.mimetype.check.whitelist.mimetypes=BAD;image/png"); - } - - public void mimetypeListBadDetectedTypeTest() - { - // Tika may detect a mimetype we have not registered, so let it through - setter.setProperties( - "transformer.strict.mimetype.check.whitelist.mimetypes=image/png;BAD"); - } - + @Test + public void debugLogSizeTest() + { + setter.setProperties( + "transformer.log.entries=12\n" + + "transformer.debug.entries=-1"); + + verify(transformerProperties).setProperties(expectedProperties( + "transformer.debug.entries", "-1", + "transformer.log.entries", "12")); + } + + @Test + public void mimetypeListTest() + { + setter.setProperties( + "transformer.strict.mimetype.check.whitelist.mimetypes=image/png;application/pdf"); + + verify(transformerProperties).setProperties(expectedProperties( + "transformer.strict.mimetype.check.whitelist.mimetypes", "image/png;application/pdf")); + } + + public void mimetypeListBlankTest() + { + setter.setProperties( + "transformer.strict.mimetype.check.whitelist.mimetypes="); + + verify(transformerProperties).setProperties(expectedProperties( + "transformer.strict.mimetype.check.whitelist.mimetypes", "")); + } + + @Test(expected=IllegalArgumentException.class) + public void mimetypeListUnevenTest() + { + setter.setProperties( + "transformer.strict.mimetype.check.whitelist.mimetypes=image/png"); + } + + @Test(expected=IllegalArgumentException.class) + public void mimetypeListBadDeclaredTypeTest() + { + setter.setProperties( + "transformer.strict.mimetype.check.whitelist.mimetypes=BAD;image/png"); + } + + public void mimetypeListBadDetectedTypeTest() + { + // Tika may detect a mimetype we have not registered, so let it through + setter.setProperties( + "transformer.strict.mimetype.check.whitelist.mimetypes=image/png;BAD"); + } + @Test(expected=IllegalArgumentException.class) public void badPropertyNameTest() { @@ -572,7 +572,7 @@ public class TransformerPropertySetterTest } @Test - public void removeSimplePropetyTest() + public void removeSimplePropertyTest() { mockProperties(transformerProperties, "transformer.log.entries", "12"); diff --git a/src/test/resources/log4j.properties b/src/test/resources/log4j.properties index 1ce9e6f8e8..d710d1ab11 100644 --- a/src/test/resources/log4j.properties +++ b/src/test/resources/log4j.properties @@ -59,9 +59,6 @@ log4j.logger.org.apache.myfaces.el.VariableResolverImpl=error log4j.logger.org.apache.myfaces.application.jsp.JspViewHandlerImpl=error log4j.logger.org.apache.myfaces.taglib=error -# OpenOfficeConnection -log4j.logger.net.sf.jooreports.openoffice.connection=fatal - # log prepared statement cache activity ### log4j.logger.org.hibernate.ps.PreparedStatementCache=info @@ -105,7 +102,6 @@ log4j.logger.org.alfresco.repo.admin.ConfigurationChecker=info log4j.logger.org.alfresco.repo.node.index.AbstractReindexComponent=warn log4j.logger.org.alfresco.repo.node.index.IndexTransactionTracker=warn log4j.logger.org.alfresco.repo.node.index.FullIndexRecoveryComponent=info -log4j.logger.org.alfresco.util.OpenOfficeConnectionTester=info log4j.logger.org.alfresco.repo.node.db.hibernate.HibernateNodeDaoServiceImpl=warn log4j.logger.org.alfresco.repo.domain.hibernate.DirtySessionMethodInterceptor=warn log4j.logger.org.alfresco.repo.transaction.RetryingTransactionHelper=debug