Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

XWIKI-22481: Add the ability to use a LibreOffice binary from another server #3610

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import java.io.File;
import java.io.InputStream;
import java.util.Optional;

import javax.inject.Inject;
import javax.inject.Singleton;
Expand All @@ -39,6 +40,7 @@
import org.xwiki.officeimporter.server.OfficeServer;
import org.xwiki.officeimporter.server.OfficeServerConfiguration;
import org.xwiki.officeimporter.server.OfficeServerException;
import org.xwiki.text.StringUtils;

/**
* Default {@link OfficeServer} implementation.
Expand Down Expand Up @@ -109,35 +111,10 @@ public DefaultOfficeServer()
public void initialize() throws OfficeServerException
{
if (this.config.getServerType() == OfficeServerConfiguration.SERVER_TYPE_INTERNAL) {
LocalOfficeManager.Builder configuration = LocalOfficeManager.builder();
configuration.portNumbers(this.config.getServerPorts());

String homePath = this.config.getHomePath();
if (homePath != null) {
configuration.officeHome(homePath);
}

String profilePath = this.config.getProfilePath();
if (profilePath != null) {
configuration.templateProfileDir(new File(profilePath));
}

configuration.maxTasksPerProcess(this.config.getMaxTasksPerProcess());
configuration.taskExecutionTimeout(this.config.getTaskExecutionTimeout());

try {
this.jodManager = configuration.build();
} catch (Exception e) {
// Protect against exceptions raised by JodManager. For example if it cannot autodetect the office home,
// it'll throw an java.lang.IllegalStateException exception...
// We wrap this in an OfficeServerException in order to display some nicer message to the user.
throw new OfficeServerException("Failed to start Office server. Reason: " + e.getMessage(), e);
}
} else if (this.config.getServerType() == OfficeServerConfiguration.SERVER_TYPE_EXTERNAL_LOCAL) {
ExternalOfficeManager.Builder externalProcessOfficeManager = ExternalOfficeManager.builder();
externalProcessOfficeManager.portNumbers(this.config.getServerPorts());
externalProcessOfficeManager.connectOnStart(true);
this.jodManager = externalProcessOfficeManager.build();
initializeInternalServer();
} else if (this.config.getServerType() == OfficeServerConfiguration.SERVER_TYPE_EXTERNAL_LOCAL
|| this.config.getServerType() == OfficeServerConfiguration.SERVER_TYPE_EXTERNAL_REMOTE) {
initializeExternalServer();
} else {
setState(ServerState.CONF_ERROR);
throw new OfficeServerException("Invalid office server configuration.");
Expand Down Expand Up @@ -166,8 +143,58 @@ public void initialize() throws OfficeServerException
.filterChain(new LinkedImagesEmbedderFilter()).build();
}

File workDir = this.environment.getTemporaryDirectory();
this.converter = new DefaultOfficeConverter(this.jodConverter, workDir);
this.converter = new DefaultOfficeConverter(this.jodConverter, getWorkDir());
}

private void initializeInternalServer() throws OfficeServerException
{
LocalOfficeManager.Builder configuration = LocalOfficeManager.builder();
configuration.portNumbers(this.config.getServerPorts());

String homePath = this.config.getHomePath();
if (homePath != null) {
configuration.officeHome(homePath);
}

String profilePath = this.config.getProfilePath();
if (profilePath != null) {
configuration.templateProfileDir(new File(profilePath));
}

configuration.maxTasksPerProcess(this.config.getMaxTasksPerProcess());
configuration.taskExecutionTimeout(this.config.getTaskExecutionTimeout());

try {
this.jodManager = configuration.build();
} catch (Exception e) {
// Protect against exceptions raised by JodManager. For example if it cannot autodetect the office home,
// it'll throw an java.lang.IllegalStateException exception...
// We wrap this in an OfficeServerException in order to display some nicer message to the user.
throw new OfficeServerException("Failed to start Office server. Reason: " + e.getMessage(), e);
}
}

private void initializeExternalServer()
{
ExternalOfficeManager.Builder externalProcessOfficeManager = ExternalOfficeManager.builder();
externalProcessOfficeManager.portNumbers(this.config.getServerPorts());
externalProcessOfficeManager.connectOnStart(true);
if (this.config.getServerType() == OfficeServerConfiguration.SERVER_TYPE_EXTERNAL_REMOTE) {
externalProcessOfficeManager.hostName(config.getServerHost());
}
this.jodManager = externalProcessOfficeManager.build();
}

private File getWorkDir()
{
Optional<String> workDirFromConfiguration = this.config.getWorkDir();
if (workDirFromConfiguration.isPresent() && StringUtils.isNotBlank(workDirFromConfiguration.get())) {
File workDir = new File(workDirFromConfiguration.get());
if (workDir.isDirectory() && workDir.canWrite()) {
return workDir;
}
}
return this.environment.getTemporaryDirectory();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import java.io.File;
import java.util.List;
import java.util.Optional;

import javax.inject.Inject;
import javax.inject.Singleton;
Expand Down Expand Up @@ -89,6 +90,12 @@ public int getServerType()
return this.configuration.getProperty(PREFIX + "serverType", DEFAULT_SERVER_TYPE);
}

@Override
public String getServerHost()
{
return this.configuration.getProperty(PREFIX + "host", DEFAULT_SERVER_HOST);
}

@Override
public int getServerPort()
{
Expand Down Expand Up @@ -134,6 +141,12 @@ public String getHomePath()
return homePath;
}

@Override
public Optional<String> getWorkDir()
{
return Optional.ofNullable(this.configuration.getProperty(PREFIX + "workDir"));
}

@Override
public String getProfilePath()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
package org.xwiki.officeimporter.server;

import org.xwiki.component.annotation.Role;
import org.xwiki.stability.Unstable;

import java.util.Optional;

/**
* Configuration properties for the {@link OfficeServer}. They are defined in XWiki's global configuration file using
Expand All @@ -46,6 +49,14 @@ public interface OfficeServerConfiguration
*/
int SERVER_TYPE_EXTERNAL_REMOTE = 2;

/**
* Default host name of the office server instance.
* Coming from org.jodconverter.local.office.ExternalOfficeManager.DEFAULT_HOSTNAME
* @since 16.10.0RC1
* @since 16.4.5
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be 16.4.6 (as used below).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And that's also Unstable

*/
String DEFAULT_SERVER_HOST = "127.0.0.1";

/**
* Returns the type of the office server instance consumed by office importer module:
* <ul>
Expand All @@ -58,6 +69,20 @@ public interface OfficeServerConfiguration
*/
int getServerType();

/**
* Returns the hostname of the office server instance, used only when the office server is externally managed and
* remotely deployed.
* @return the hostname of the office server instance
* @since 16.10.0RC1
* @since 16.4.6
*/
@Unstable
default String getServerHost()
surli marked this conversation as resolved.
Show resolved Hide resolved
{
// Coming from org.jodconverter.local.office.ExternalOfficeManager.DEFAULT_HOSTNAME
return DEFAULT_SERVER_HOST;
}

/**
* @return the port number used for connecting to the office server instance
* @deprecated Since 12.1RC1. Now use {@link #getServerPorts()}.
Expand Down Expand Up @@ -91,6 +116,18 @@ default int[] getServerPorts()
*/
String getProfilePath();

/**
* @return the path where the files are exchanged between XWiki and the office server (if absent or blank: use the
* default environment temporary directory)
* @since 16.10.0RC1
* @since 16.4.6
*/
@Unstable
default Optional<String> getWorkDir()
{
return Optional.empty();
}

/**
* @return the maximum number of simultaneous conversion tasks to be handled by a single office process instance
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-->

<xwikidoc version="1.4" reference="XWiki.OfficeImporterAdmin" locale="">
<xwikidoc version="1.5" reference="XWiki.OfficeImporterAdmin" locale="">
<web>XWiki</web>
<name>OfficeImporterAdmin</name>
<language/>
Expand Down Expand Up @@ -108,6 +108,18 @@
&lt;/dt&gt;
&lt;dd&gt;$escapetool.html($serverType)&lt;/dd&gt;
###
### Server Host
###
#if ($services.officemanager.config.serverType == 2)
&lt;dt&gt;
&lt;label&gt;$escapetool.html($services.localization.render('xe.officeimporter.openoffice.serverhost'))&lt;/label&gt;
Copy link
Member

@vmassol vmassol Nov 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm this is using old translation key format, I think we need to fix this. See https://dev.xwiki.org/xwiki/bin/view/Community/DevelopmentPractices#HTranslationPropertyNaming

&lt;span class="xHint"&gt;
$escapetool.xml($services.localization.render('office.config.serverHost.hint'))
&lt;/span&gt;
&lt;/dt&gt;
&lt;dd&gt;$escapetool.html($services.officemanager.config.serverHost)&lt;/dd&gt;
#end
###
### Server Port
###
&lt;dt&gt;
Expand Down Expand Up @@ -166,6 +178,13 @@
&lt;/dd&gt;
#end
###
### Work directory
###
#if ($services.officemanager.config.workDir.isPresent())
&lt;dt&gt;&lt;label&gt;$escapetool.html($services.localization.render('xe.officeimporter.openoffice.workdir'))&lt;/label&gt;&lt;/dt&gt;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment re translation key format

&lt;dd&gt;$escapetool.html($services.officemanager.config.workDir.get())&lt;/dd&gt;
#end
###
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if it's useful to always display that information. Looks a bit technical and more for debug purposes. Let's leave it like this for now but we may want to only display it for advanced users or when in debug mode (debug = true in the query string for example).

### Server State
###
&lt;dt&gt;&lt;label&gt;$escapetool.html($services.localization.render('xe.officeimporter.openoffice.serverstate'))&lt;/label&gt;&lt;/dt&gt;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ office.config.serverState.connected=Connected
office.config.serverState.notConnected=Not Connected
office.config.serverState.confError=Invalid Configuration
office.config.serverState.error=Error
office.config.serverHost=Server host
office.config.serverHost.hint=The hostname of the office server instance.
office.config.workDir=Work directory

## Used to indicate where deprecated keys start
#@deprecatedstart
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -348,8 +348,15 @@ rendering.transformations = $xwikiRenderingTransformations
#-# Type of the openoffice server instance used by officeimporter component.
#-# 0 - Internally managed server instance. (Default)
#-# 1 - Externally managed (local) server instance.
#-# 2 - Externally managed (remotely) server instance. (Since 16.10.0RC1, 16.4.6)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/remotely/remote

# openoffice.serverType = 0

#-# [Since 16.10.0RC1]
#-# [Since 16.4.6]
#-# Hostname used for connecting to the openoffice server instance when openoffice.serverType = 2
#-# Default value is 127.0.0.1
# openoffice.host = 127.0.0.1

#-# [Since 12.1RC1]
#-# Port numbers used for connecting to the openoffice server instance.
#-# For an internally managed server instance, it will create the process for all ports.
Expand All @@ -371,6 +378,13 @@ rendering.transformations = $xwikiRenderingTransformations
#-# If no path is provided, a default value will be calculated based on the operating environment.
# openoffice.profilePath = /home/user/.openoffice.org/3

#-# [Since 16.10.0RC1]
#-# [Since 16.4.6]
#-# Path to a folder where XWiki will exchange temporary files with the openoffice server.
#-# If no path is provided, the temporary folder set for XWiki will be used.
#-# If openoffice.serverType = 2, this folder should be a shared volume between the two servers.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should or must?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If openoffice.serverType = 2, this folder should be a shared volume between the two servers.

Hmmm I missed that @gdelhumeau if your plan is to have a shared volume, then why shouldn't you consider the LO as externally but locally installed (serverType=1)?

# openoffice.workDir =

#-# [Since 1.8RC3]
#-# Maximum number of simultaneous conversion tasks to be handled by a single openoffice process (serverType:0 only).
#-# Default value is 50
Expand Down