Skip to content

Commit

Permalink
Open office process connection timeout added (#127)
Browse files Browse the repository at this point in the history
Co-authored-by: IlyaChekashkin <[email protected]>
  • Loading branch information
2 people authored and subbotin committed Nov 8, 2020
1 parent 32a46d1 commit ee25716
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@

/**
* A bootstrap connector which establishes a connection to an OOo server.
*
* <p>
* Most of the source code in this class has been taken from the Java class
* "Bootstrap.java" (Revision: 1.15) from the UDK projekt (Uno Software Develop-
* ment Kit) from OpenOffice.org (http:https://udk.openoffice.org/). The source code
* is available for example through a browser based online version control
* access at http:https://udk.openoffice.org/source/browse/udk/. The Java class
* "Bootstrap.java" is there available at
* http:https://udk.openoffice.org/source/browse/udk/javaunohelper/com/sun/star/comp/helper/Bootstrap.java?view=markup
*
* <p>
* The idea to develop this BootstrapConnector comes from the blog "Getting
* started with the OpenOffice.org API part III : starting OpenOffice.org with
* jars not in the OOo install dir by Wouter van Reeven"
Expand All @@ -48,54 +48,62 @@
*/
public class BootstrapConnector {

/** The OOo server. */
/**
* The OOo server.
*/
private OOServer oooServer;

/** The connection string which has ben used to establish the connection. */

/**
* The connection string which has ben used to establish the connection.
*/
private String oooConnectionString;

protected int connectionTimeoutSec;

protected static final int CONNECTION_RETRY_INTERVAL = 500;

/**
* Constructs a bootstrap connector which connects to the specified
* OOo server.
*
* @param oooServer The OOo server
*
* @param oooServer The OOo server
*/
public BootstrapConnector(OOServer oooServer) {

public BootstrapConnector(OOServer oooServer, int connectionTimeoutSec) {
this.oooServer = oooServer;
this.oooConnectionString = null;
this.connectionTimeoutSec = connectionTimeoutSec;
}

/**
* Connects to an OOo server using the specified accept option and
* connection string and returns a component context for using the
* connection to the OOo server.
*
* <p>
* The accept option and the connection string should match to get a
* connection. OOo provides to different types of connections:
* 1) The socket connection
* 2) The named pipe connection
*
* <p>
* To create a socket connection a host and port must be provided.
* For example using the host "localhost" and the port "8100" the
* accept option and connection string looks like this:
* - accept option : -accept=socket,host=localhost,port=8100;urp;
* - connection string: uno:socket,host=localhost,port=8100;urp;StarOffice.ComponentContext
*
* <p>
* To create a named pipe a pipe name must be provided. For example using
* the pipe name "oooPipe" the accept option and connection string looks
* like this:
* - accept option : -accept=pipe,name=oooPipe;urp;
* - connection string: uno:pipe,name=oooPipe;urp;StarOffice.ComponentContext
*
* @param oooConnectionString The connection string
* @return The component context
*
* @param oooConnectionString The connection string
* @return The component context
*/
public XComponentContext connect(String oooConnectionString) throws BootstrapException {

this.oooConnectionString = oooConnectionString;

XComponentContext xContext = null;
XComponentContext xContext;
try {
// get local context
XComponentContext xLocalContext = getLocalContext();
Expand All @@ -104,24 +112,26 @@ public XComponentContext connect(String oooConnectionString) throws BootstrapExc

// initial service manager
XMultiComponentFactory xLocalServiceManager = xLocalContext.getServiceManager();
if ( xLocalServiceManager == null )
if (xLocalServiceManager == null)
throw new BootstrapException("no initial service manager!");

// create a URL resolver
XUnoUrlResolver xUrlResolver = UnoUrlResolver.create(xLocalContext);

// wait until office is started
for (int i = 0;; ++i) {
long connectionTimeoutMillis = connectionTimeoutSec * 1000;
// wait until office is started but no longer than connectionTimeoutMillis
long start = System.currentTimeMillis();
for (; ; ) {
try {
xContext = getRemoteContext(xUrlResolver);
break;
} catch ( NoConnectException ex ) {
// Wait 500 ms, then try to connect again, but do not wait
// longer than 5 sec total:
if (i == 10) {
throw new BootstrapException(ex);
} catch (NoConnectException ex) {
if (System.currentTimeMillis() - start < connectionTimeoutMillis) {
// Retry to connect after a short interval
Thread.sleep(CONNECTION_RETRY_INTERVAL);
} else {
throw new BootstrapException("Unable to connect to the OO process", ex);
}
Thread.sleep(500);
}
}
} catch (RuntimeException e) {
Expand All @@ -135,9 +145,9 @@ public XComponentContext connect(String oooConnectionString) throws BootstrapExc
/**
* Disconnects from an OOo server using the connection string from the
* previous connect.
*
* <p>
* If there has been no previous connect, the disconnects does nothing.
*
* <p>
* If there has been a previous connect, disconnect tries to terminate
* the OOo server and kills the OOo server process the connect started.
*/
Expand All @@ -158,11 +168,11 @@ public void disconnect() {
XComponentContext xRemoteContext = getRemoteContext(xUrlResolver);

// get desktop to terminate office
Object desktop = xRemoteContext.getServiceManager().createInstanceWithContext("com.sun.star.frame.Desktop",xRemoteContext);
Object desktop = xRemoteContext.getServiceManager().createInstanceWithContext(
"com.sun.star.frame.Desktop", xRemoteContext);
XDesktop xDesktop = (XDesktop) UnoRuntime.queryInterface(XDesktop.class, desktop);
xDesktop.terminate();
}
catch (Exception e) {
} catch (Exception e) {
// Bad luck, unable to terminate office
}

Expand All @@ -172,8 +182,8 @@ public void disconnect() {

/**
* Create default local component context.
*
* @return The default local component context
*
* @return The default local component context
*/
protected XComponentContext getLocalContext() throws BootstrapException, Exception {

Expand All @@ -186,10 +196,11 @@ protected XComponentContext getLocalContext() throws BootstrapException, Excepti

/**
* Try to connect to office.
*
* @return The remote component context
*
* @return The remote component context
*/
protected XComponentContext getRemoteContext(XUnoUrlResolver xUrlResolver) throws BootstrapException, ConnectionSetupException, IllegalArgumentException, NoConnectException {
protected XComponentContext getRemoteContext(XUnoUrlResolver xUrlResolver) throws BootstrapException,
ConnectionSetupException, IllegalArgumentException, NoConnectException {

Object context = xUrlResolver.resolve(oooConnectionString);
XComponentContext xContext = (XComponentContext) UnoRuntime.queryInterface(XComponentContext.class, context);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ public class BootstrapSocketConnector extends BootstrapConnector {
*
* @param oooServer The OOo server
*/
public BootstrapSocketConnector(OOServer oooServer) {
super(oooServer);
public BootstrapSocketConnector(OOServer oooServer, int connectionTimeoutSec) {
super(oooServer, connectionTimeoutSec);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public OfficeConnection(String openOfficePath, Integer port, ProcessManager proc
this.officeIntegration = officeIntegration;
this.oooServer = new OOServer(openOfficePath, OOServer.getDefaultOOoOptions(),
"localhost", port, officeIntegration.getTemporaryDirPath(), processManager);
this.bsc = new BootstrapSocketConnector(oooServer);
this.bsc = new BootstrapSocketConnector(oooServer, officeIntegration.getConnectionTimeoutSec());
this.openOfficePath = openOfficePath;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public class OfficeIntegration implements OfficeIntegrationAPI {
protected String temporaryDirPath;
protected Integer[] openOfficePorts;
protected Integer timeoutInSeconds = DEFAULT_TIMEOUT;
protected int connectionTimeoutSec = DEFAULT_CONNECTION_TIMEOUT;
protected int countOfRetry = DEFAULT_RETRY_COUNT;
protected int retryIntervalMs = DEFAULT_RETRY_INTERVAL;
protected Boolean displayDeviceAvailable = false;
Expand Down Expand Up @@ -78,6 +79,14 @@ public Integer getTimeoutInSeconds() {
return timeoutInSeconds;
}

public int getConnectionTimeoutSec() {
return connectionTimeoutSec;
}

public void setConnectionTimeoutSec(int connectionTimeoutSec) {
this.connectionTimeoutSec = connectionTimeoutSec;
}

public Boolean isDisplayDeviceAvailable() {
return displayDeviceAvailable;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public interface OfficeIntegrationAPI {
int DEFAULT_RETRY_COUNT = 2;
int DEFAULT_RETRY_INTERVAL = 1000;
int DEFAULT_TIMEOUT = 60;
int DEFAULT_CONNECTION_TIMEOUT = 15;

String getTemporaryDirPath();

Expand Down

0 comments on commit ee25716

Please sign in to comment.