package com.gradwell.maclibreofficebootstrap; import com.sun.star.bridge.UnoUrlResolver; import com.sun.star.bridge.XUnoUrlResolver; import com.sun.star.comp.helper.Bootstrap; import static com.sun.star.comp.helper.Bootstrap.createInitialComponentContext; import com.sun.star.comp.helper.BootstrapException; import com.sun.star.lang.XMultiComponentFactory; import com.sun.star.lib.util.NativeLibraryLoader; import com.sun.star.uno.UnoRuntime; import com.sun.star.uno.XComponentContext; import java.io.BufferedReader; import java.io.File; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintStream; import java.io.UnsupportedEncodingException; import java.util.Map; import java.util.Random; // import com.sun.star.lib.unoloader.UnoClassLoader; // not in libreoffice-7.4.1.jar or ridl-6.4.7.jar import com.gradwell.GeneralPurposeBasic.DJLGStaticServices; // DG addition 19th Jan 2023 public class MacLibreOfficeBootstrap extends com.sun.star.comp.helper.Bootstrap { // might need to implement getDefaultOptions private static final Random randomPipeName = new Random(); public static final XComponentContext MacLibreOfficeBootstrap(String[] argArray ) throws BootstrapException { XComponentContext xContext = null; try { // create default local component context XComponentContext xLocalContext = createInitialComponentContext( (Map) null ); if ( xLocalContext == null ) { throw new BootstrapException( "no local component context!" ); } // find office executable relative to this class's class loader String sOffice; String osName = System.getProperty( "os.name" ); if (osName.startsWith( "Windows")) { sOffice = "soffice.exe"; } else // Mac and Linux { sOffice = "/Applications/LibreOffice.app/Contents/MacOS/soffice"; } /* // so DG is replacing this broken code by the new code after this comment File fOffice = null; try { Class theBootstrapClass = Bootstrap.class; // try to force the UnoClassLoader to be in the compiled code ! (Adding the ridl jar and the libreoffice jar didn't help //UnoClassLoader myUnoClassLoader = new UnoClassLoader(); // not in libreoffice-7.4.1.jar or ridl-6.4.7.jar // well the next line crashes with java.lang.NoClassDefFoundError: com/sun/star/lib/unoloader/UnoClassLoader - hence the previous ClassLoader myClassLoader = theBootstrapClass.getClassLoader(); fOffice = NativeLibraryLoader.getResource(myClassLoader , sOffice ); if ( fOffice == null ) { throw new BootstrapException( "no office executable found!" ); } } catch (Throwable t) { DJLGStaticServices.DisplayThrowable(t); if (t instanceof BootstrapException) { throw t; } } */ // create random pipe name String sPipeName = "uno" + Long.toString(randomPipeName.nextLong() & 0x7fffffffffffffffL); // create call with arguments String[] cmdArray = new String[ argArray.length + 2 ]; cmdArray[0] = sOffice; //fOffice.getPath(); cmdArray[1] = ( "--accept=pipe,name=" + sPipeName + ";urp;" ); System.arraycopy( argArray, 0, cmdArray, 2, argArray.length ); // start office process Process p = Runtime.getRuntime().exec( cmdArray ); pipe( p.getInputStream(), System.out, "CO> " ); pipe( p.getErrorStream(), System.err, "CE> " ); // 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 ); // connection string String sConnect = "uno:pipe,name=" + sPipeName + ";urp;StarOffice.ComponentContext"; // wait until office is started for (int i = 0;; ++i) { try { // try to connect to office Object context = xUrlResolver.resolve( sConnect ); xContext = UnoRuntime.queryInterface( XComponentContext.class, context); if ( xContext == null ) throw new BootstrapException( "no component context!" ); 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); } Thread.sleep( 500 ); } } } catch ( BootstrapException e ) { throw e; } catch ( java.lang.RuntimeException e ) { throw e; } catch ( java.lang.Exception e ) { throw new BootstrapException( e ); } catch (Throwable t) { DJLGStaticServices.DisplayThrowable(t); int a = 1; a++; } return xContext; } // copy of that in bootstrap private static void pipe( final InputStream in, final PrintStream out, final String prefix ) { Thread myThread = new Thread( "Pipe: " + prefix) { @Override public void run() { try { BufferedReader r = new BufferedReader( new InputStreamReader(in, "UTF-8") ); for ( ; ; ) { String s = r.readLine(); if ( s == null ) { break; } out.println( prefix + s ); } } catch ( UnsupportedEncodingException e ) { e.printStackTrace( System.err ); } catch ( java.io.IOException e ) { e.printStackTrace( System.err ); } } }; //.start(); myThread.start(); } }