Skip to content

Commit

Permalink
First commit of bootstrap-connector
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremysolarz committed May 20, 2017
0 parents commit 7c42535
Show file tree
Hide file tree
Showing 8 changed files with 809 additions and 0 deletions.
3 changes: 3 additions & 0 deletions META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
Manifest-Version: 1.0
Created-By: 1.5.0_14 (Sun Microsystems Inc.)

50 changes: 50 additions & 0 deletions README.md
@@ -0,0 +1,50 @@
# Introduction

This is a short How-To for quickly solving the regularly occurring error "no office executable found!".
You can read a huge number of threads in various OpenOffice.org forums dealing with this problem.
This error is caused by using the [Bootstrap Connection Mechanism](https://forum.openoffice.org/en/forum/viewtopic.php?f=44&t=1013) (introduced with OOo 2.x) in
conjunction with
moving
or copying "juh.jar" (OOo's "Java UNO Helper" JAR file containing the class file "Bootstrap.class") from the subfolder
"program\classes" of the OOo installation folder (which is for example on Windows "c:\program files\OpenOffice.org 2.3")
to another folder (mostly a subfolder, which is directly accessible from a web container or web server like for
example Tomcat).

# How-to
So, if you're encountering **"no office executable found!"** follow these steps:

1. Download the file "bootstrapconnector.jar" attached to this post and save it.
1. Put the JAR file "bootstrapconnector.jar" for example in the same folder, where you put "juh.jar", and add it to
your CLASSPATH or add it in your IDE to the libraries for source code compiling (for example open in NetBeans the
project properties and select there "Libraries" > tab "Compile" > press "Add JAR/Folder" > locate the "bootstrapconnector.jar" and press "Open").
1. Determine the folder of your OpenOffice.org executable "soffice.exe" (on Windows systems) or "soffice" (on *nix
systems). On Windows it might be something like "c:\program files\OpenOffice.org 2.3\program\", and on *nix for example something like "/opt/openoffice.org2.3/program" or "/usr/lib/openoffice.org/program".
1. Edit your Java source code file, that tries to get the connection by calling "Bootstrap.bootstrap()". This is mostly
done with a Java source code line looking like this:<br>
```XComponentContext xContext = Bootstrap.bootstrap();```
Perform the following steps in this Java source file:
1. Add the following line to your import statements:<br/>
```import ooo.connector.BootstrapSocketConnector;```
1. Add a line above "Bootstrap.bootstrap()" to assign the name of the folder of your OpenOffice.org executable to a String variable:<br/>
```String oooExeFolder = "C:/Program Files/OpenOffice.org 2.3/program/";```
1. Change the call of "Bootstrap.bootstrap()" to "BootstrapSocketConnector.bootstrap(oooExeFolder)":
```XComponentContext xContext = BootstrapSocketConnector.bootstrap(oooExeFolder);```
1. Save and compile the edited file and see if "no office executable found!" has really vanished.
1. If you want to learn more about what you can do with "bootstrapconnector.jar", stay tuned. (To be continued...)

# Credits

Most of the source code in the attached JAR file has been taken from the Java class "Bootstrap.java" (Revision: 1.15)
from the UDK project (Uno Software Development Kit) from OpenOffice.org (http://udk.openoffice.org/).
The source code is available for example through a browser based online version control access at http://udk
.openoffice.org/source/browse/udk/. The Java class "Bootstrap.java" is there available at
http://www.openoffice.org/udk/source/browse/udk/javaunohelper/com/sun/star/comp/helper/Bootstrap.java?view=markup

The idea to develop the BootstrapConnector, BootstrapSocketConnector and BootstrapPipeConnector 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" (http://technology.amis.nl/blog/?p=1284) and from various posts in the "(Unofficial) OpenOffice.org
Forum" at http://www.oooforum.org/ and this forum complaining about "no office executable found!".

## Source
Taken from
[https://forum.openoffice.org/en/forum/viewtopic.php?f=44&t=2520](https://forum.openoffice.org/en/forum/viewtopic.php?f=44&t=2520#).
53 changes: 53 additions & 0 deletions pom.xml
@@ -0,0 +1,53 @@
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>ooo.connector</groupId>
<artifactId>bootstrap-connector</artifactId>
<version>1.0.0</version>

<properties>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
<dependency>
<groupId>org.libreoffice</groupId>
<artifactId>juh</artifactId>
<version>5.3.2</version>
</dependency>
<dependency>
<groupId>org.libreoffice</groupId>
<artifactId>jurt</artifactId>
<version>5.3.2</version>
</dependency>
<dependency>
<groupId>org.libreoffice</groupId>
<artifactId>ridl</artifactId>
<version>5.3.2</version>
</dependency>
<dependency>
<groupId>org.libreoffice</groupId>
<artifactId>unoil</artifactId>
<version>5.3.2</version>
</dependency>
<dependency>
<groupId>org.libreoffice</groupId>
<artifactId>officebean</artifactId>
<version>5.3.2</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<compilerArgument>-Xlint:unchecked</compilerArgument>
</configuration>
</plugin>
</plugins>
</build>
</project>
220 changes: 220 additions & 0 deletions src/main/java/ooo/connector/BootstrapConnector.java
@@ -0,0 +1,220 @@
package ooo.connector;

import com.sun.star.bridge.UnoUrlResolver;
import com.sun.star.bridge.XUnoUrlResolver;
import com.sun.star.comp.helper.Bootstrap;
import com.sun.star.comp.helper.BootstrapException;
import com.sun.star.connection.ConnectionSetupException;
import com.sun.star.connection.NoConnectException;
import com.sun.star.frame.XDesktop;
import com.sun.star.lang.IllegalArgumentException;
import com.sun.star.lang.XMultiComponentFactory;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XComponentContext;
import ooo.connector.server.OOoServer;

/**
* A bootstrap connector which establishes a connection to an OOo server.
*
* 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://udk.openoffice.org/). The source code
* is available for example through a browser based online version control
* access at http://udk.openoffice.org/source/browse/udk/. The Java class
* "Bootstrap.java" is there available at
* http://udk.openoffice.org/source/browse/udk/javaunohelper/com/sun/star/comp/helper/Bootstrap.java?view=markup
*
* 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"
* (http://technology.amis.nl/blog/?p=1284) and from various posts in the
* "(Unofficial) OpenOffice.org Forum" at http://www.oooforum.org/ and the
* "OpenOffice.org Community Forum" at http://user.services.openoffice.org/
* complaining about "no office executable found!".
*/
public class BootstrapConnector {

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

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

/**
* Constructs a bootstrap connector which uses the folder of the OOo
* installation containing the soffice executable.
*
* @param oooExecFolder The folder of the OOo installation containing the soffice executable
*/
public BootstrapConnector(String oooExecFolder) {

this.oooServer = new OOoServer(oooExecFolder);
this.oooConnectionString = null;
}

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

this.oooServer = oooServer;
this.oooConnectionString = null;
}

/**
* 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.
*
* 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
*
* 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
*
* 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 oooAcceptOption The accept option
* @param oooConnectionString The connection string
* @return The component context
*/
public XComponentContext connect(String oooAcceptOption, String oooConnectionString) throws BootstrapException {

this.oooConnectionString = oooConnectionString;

XComponentContext xContext = null;
try {
// get local context
XComponentContext xLocalContext = getLocalContext();

oooServer.start(oooAcceptOption);

// initial service manager
XMultiComponentFactory xLocalServiceManager = xLocalContext.getServiceManager();
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) {
try {
xContext = getRemoteContext(xUrlResolver);
break;
} catch ( com.sun.star.connection.NoConnectException ex ) {
// Wait 500 ms, then try to connect again, but do not wait
// longer than 5 min (= 600 * 500 ms) total:
if (i == 600) {
throw new BootstrapException(ex.toString());
}
Thread.sleep(500);
}
}
} catch (java.lang.RuntimeException e) {
throw e;
} catch (java.lang.Exception e) {
throw new BootstrapException(e);
}
return xContext;
}

/**
* Disconnects from an OOo server using the connection string from the
* previous connect.
*
* If there has been no previous connect, the disconnects does nothing.
*
* If there has been a previous connect, disconnect tries to terminate
* the OOo server and kills the OOo server process the connect started.
*/
public void disconnect() {

if (oooConnectionString == null)
return;

// call office to terminate itself
try {
// get local context
XComponentContext xLocalContext = getLocalContext();

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

// get remote context
XComponentContext xRemoteContext = getRemoteContext(xUrlResolver);

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

oooServer.kill();
oooConnectionString = null;
}

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

XComponentContext xLocalContext = Bootstrap.createInitialComponentContext(null);
if (xLocalContext == null) {
throw new BootstrapException("no local component context!");
}
return xLocalContext;
}

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

Object context = xUrlResolver.resolve(oooConnectionString);
XComponentContext xContext = (XComponentContext) UnoRuntime.queryInterface(XComponentContext.class, context);
if (xContext == null) {
throw new BootstrapException("no component context!");
}
return xContext;
}

/**
* Bootstraps a connection to an OOo server in the specified soffice
* executable folder of the OOo installation using the specified accept
* option and connection string and returns a component context for using
* the connection to the OOo server.
*
* The accept option and the connection string should match in connection
* type and pipe name or host and port to get a connection.
*
* @param oooExecFolder The folder of the OOo installation containing the soffice executable
* @param oooAcceptOption The accept option
* @param oooConnectionString The connection string
* @return The component context
*/
public static final XComponentContext bootstrap(String oooExecFolder, String oooAcceptOption, String oooConnectionString) throws BootstrapException {

BootstrapConnector bootstrapConnector = new BootstrapConnector(oooExecFolder);
return bootstrapConnector.connect(oooAcceptOption, oooConnectionString);
}
}

0 comments on commit 7c42535

Please sign in to comment.