1a5b190bfSAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3a5b190bfSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4a5b190bfSAndrew Rist * or more contributor license agreements. See the NOTICE file 5a5b190bfSAndrew Rist * distributed with this work for additional information 6a5b190bfSAndrew Rist * regarding copyright ownership. The ASF licenses this file 7a5b190bfSAndrew Rist * to you under the Apache License, Version 2.0 (the 8a5b190bfSAndrew Rist * "License"); you may not use this file except in compliance 9a5b190bfSAndrew Rist * with the License. You may obtain a copy of the License at 10a5b190bfSAndrew Rist * 11a5b190bfSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12a5b190bfSAndrew Rist * 13a5b190bfSAndrew Rist * Unless required by applicable law or agreed to in writing, 14a5b190bfSAndrew Rist * software distributed under the License is distributed on an 15a5b190bfSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16a5b190bfSAndrew Rist * KIND, either express or implied. See the License for the 17a5b190bfSAndrew Rist * specific language governing permissions and limitations 18a5b190bfSAndrew Rist * under the License. 19a5b190bfSAndrew Rist * 20a5b190bfSAndrew Rist *************************************************************/ 21a5b190bfSAndrew Rist 22a5b190bfSAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir package com.sun.star.comp.helper; 25cdf0e10cSrcweir 26cdf0e10cSrcweir import com.sun.star.bridge.UnoUrlResolver; 27cdf0e10cSrcweir import com.sun.star.bridge.XUnoUrlResolver; 28cdf0e10cSrcweir import com.sun.star.comp.loader.JavaLoader; 29cdf0e10cSrcweir import com.sun.star.container.XSet; 30cdf0e10cSrcweir import com.sun.star.lang.XInitialization; 31cdf0e10cSrcweir import com.sun.star.lang.XMultiServiceFactory; 32cdf0e10cSrcweir import com.sun.star.lang.XMultiComponentFactory; 33cdf0e10cSrcweir import com.sun.star.lang.XSingleComponentFactory; 34cdf0e10cSrcweir import com.sun.star.lib.util.NativeLibraryLoader; 35cdf0e10cSrcweir import com.sun.star.loader.XImplementationLoader; 36cdf0e10cSrcweir import com.sun.star.uno.UnoRuntime; 37cdf0e10cSrcweir import com.sun.star.uno.XComponentContext; 38cdf0e10cSrcweir 39cdf0e10cSrcweir import java.io.BufferedReader; 40cdf0e10cSrcweir import java.io.File; 41cdf0e10cSrcweir import java.io.InputStream; 42cdf0e10cSrcweir import java.io.InputStreamReader; 43cdf0e10cSrcweir import java.io.PrintStream; 44cdf0e10cSrcweir import java.util.Enumeration; 45cdf0e10cSrcweir import java.util.Hashtable; 46cdf0e10cSrcweir import java.util.Random; 47cdf0e10cSrcweir 48cdf0e10cSrcweir /** Bootstrap offers functionality to obtain a context or simply 49cdf0e10cSrcweir a service manager. 50cdf0e10cSrcweir The service manager can create a few basic services, whose implementations are: 51cdf0e10cSrcweir <ul> 52cdf0e10cSrcweir <li>com.sun.star.comp.loader.JavaLoader</li> 53cdf0e10cSrcweir <li>com.sun.star.comp.urlresolver.UrlResolver</li> 54cdf0e10cSrcweir <li>com.sun.star.comp.bridgefactory.BridgeFactory</li> 55cdf0e10cSrcweir <li>com.sun.star.comp.connections.Connector</li> 56cdf0e10cSrcweir <li>com.sun.star.comp.connections.Acceptor</li> 57cdf0e10cSrcweir <li>com.sun.star.comp.servicemanager.ServiceManager</li> 58cdf0e10cSrcweir </ul> 59cdf0e10cSrcweir 60cdf0e10cSrcweir Other services can be inserted into the service manager by 61cdf0e10cSrcweir using its XSet interface: 62cdf0e10cSrcweir <pre> 63cdf0e10cSrcweir XSet xSet = UnoRuntime.queryInterface( XSet.class, aMultiComponentFactory ); 64cdf0e10cSrcweir // insert the service manager 65cdf0e10cSrcweir xSet.insert( aSingleComponentFactory ); 66cdf0e10cSrcweir </pre> 67cdf0e10cSrcweir */ 68cdf0e10cSrcweir public class Bootstrap { 69cdf0e10cSrcweir 70cdf0e10cSrcweir private static void insertBasicFactories( 71cdf0e10cSrcweir XSet xSet, XImplementationLoader xImpLoader ) 72cdf0e10cSrcweir throws Exception 73cdf0e10cSrcweir { 74cdf0e10cSrcweir // insert the factory of the loader 75cdf0e10cSrcweir xSet.insert( xImpLoader.activate( 76cdf0e10cSrcweir "com.sun.star.comp.loader.JavaLoader", null, null, null ) ); 77cdf0e10cSrcweir 78cdf0e10cSrcweir // insert the factory of the URLResolver 79cdf0e10cSrcweir xSet.insert( xImpLoader.activate( 80cdf0e10cSrcweir "com.sun.star.comp.urlresolver.UrlResolver", null, null, null ) ); 81cdf0e10cSrcweir 82cdf0e10cSrcweir // insert the bridgefactory 83cdf0e10cSrcweir xSet.insert( xImpLoader.activate( 84cdf0e10cSrcweir "com.sun.star.comp.bridgefactory.BridgeFactory", null, null, null ) ); 85cdf0e10cSrcweir 86cdf0e10cSrcweir // insert the connector 87cdf0e10cSrcweir xSet.insert( xImpLoader.activate( 88cdf0e10cSrcweir "com.sun.star.comp.connections.Connector", null, null, null ) ); 89cdf0e10cSrcweir 90cdf0e10cSrcweir // insert the acceptor 91cdf0e10cSrcweir xSet.insert( xImpLoader.activate( 92cdf0e10cSrcweir "com.sun.star.comp.connections.Acceptor", null, null, null ) ); 93cdf0e10cSrcweir } 94cdf0e10cSrcweir 95cdf0e10cSrcweir /** Bootstraps an initial component context with service manager and basic 96cdf0e10cSrcweir jurt components inserted. 97cdf0e10cSrcweir @param context_entries the hash table contains mappings of entry names (type string) to 98cdf0e10cSrcweir context entries (type class ComponentContextEntry). 99cdf0e10cSrcweir @return a new context. 100*2f57578eSDamjan Jovanovic @throws java.lang.Exception 101cdf0e10cSrcweir */ 102cdf0e10cSrcweir static public XComponentContext createInitialComponentContext( Hashtable context_entries ) 103cdf0e10cSrcweir throws Exception 104cdf0e10cSrcweir { 105cdf0e10cSrcweir XImplementationLoader xImpLoader = UnoRuntime.queryInterface( 106cdf0e10cSrcweir XImplementationLoader.class, new JavaLoader() ); 107cdf0e10cSrcweir 108cdf0e10cSrcweir // Get the factory of the ServiceManager 109cdf0e10cSrcweir XSingleComponentFactory smgr_fac = UnoRuntime.queryInterface( 110cdf0e10cSrcweir XSingleComponentFactory.class, xImpLoader.activate( 111cdf0e10cSrcweir "com.sun.star.comp.servicemanager.ServiceManager", null, null, null ) ); 112cdf0e10cSrcweir 113cdf0e10cSrcweir // Create an instance of the ServiceManager 114cdf0e10cSrcweir XMultiComponentFactory xSMgr = UnoRuntime.queryInterface( 115cdf0e10cSrcweir XMultiComponentFactory.class, smgr_fac.createInstanceWithContext( null ) ); 116cdf0e10cSrcweir 117cdf0e10cSrcweir // post init loader 118cdf0e10cSrcweir XInitialization xInit = UnoRuntime.queryInterface( 119cdf0e10cSrcweir XInitialization.class, xImpLoader ); 120cdf0e10cSrcweir Object[] args = new Object [] { xSMgr }; 121cdf0e10cSrcweir xInit.initialize( args ); 122cdf0e10cSrcweir 123cdf0e10cSrcweir // initial component context 124cdf0e10cSrcweir if (context_entries == null) 125cdf0e10cSrcweir context_entries = new Hashtable( 1 ); 126cdf0e10cSrcweir // add smgr 127cdf0e10cSrcweir context_entries.put( 128cdf0e10cSrcweir "/singletons/com.sun.star.lang.theServiceManager", 129cdf0e10cSrcweir new ComponentContextEntry( null, xSMgr ) ); 130cdf0e10cSrcweir // ... xxx todo: add standard entries 131cdf0e10cSrcweir XComponentContext xContext = new ComponentContext( context_entries, null ); 132cdf0e10cSrcweir 133cdf0e10cSrcweir // post init smgr 134cdf0e10cSrcweir xInit = UnoRuntime.queryInterface( 135cdf0e10cSrcweir XInitialization.class, xSMgr ); 136cdf0e10cSrcweir args = new Object [] { null, xContext }; // no registry, default context 137cdf0e10cSrcweir xInit.initialize( args ); 138cdf0e10cSrcweir 139cdf0e10cSrcweir XSet xSet = UnoRuntime.queryInterface( XSet.class, xSMgr ); 140cdf0e10cSrcweir // insert the service manager 141cdf0e10cSrcweir xSet.insert( smgr_fac ); 142cdf0e10cSrcweir // and basic jurt factories 143cdf0e10cSrcweir insertBasicFactories( xSet, xImpLoader ); 144cdf0e10cSrcweir 145cdf0e10cSrcweir return xContext; 146cdf0e10cSrcweir } 147cdf0e10cSrcweir 148cdf0e10cSrcweir /** 149cdf0e10cSrcweir * Bootstraps a servicemanager with the jurt base components registered. 150cdf0e10cSrcweir * <p> 151cdf0e10cSrcweir * @return a freshly boostrapped service manager 152cdf0e10cSrcweir * @see com.sun.star.lang.ServiceManager 153*2f57578eSDamjan Jovanovic * @throws java.lang.Exception 154cdf0e10cSrcweir */ 155cdf0e10cSrcweir static public XMultiServiceFactory createSimpleServiceManager() throws Exception 156cdf0e10cSrcweir { 157cdf0e10cSrcweir return UnoRuntime.queryInterface( 158cdf0e10cSrcweir XMultiServiceFactory.class, createInitialComponentContext( null ).getServiceManager() ); 159cdf0e10cSrcweir } 160cdf0e10cSrcweir 161cdf0e10cSrcweir 162*2f57578eSDamjan Jovanovic /** 163*2f57578eSDamjan Jovanovic * Bootstraps the initial component context from a native UNO installation. 164*2f57578eSDamjan Jovanovic * <p> 165*2f57578eSDamjan Jovanovic * @return 166*2f57578eSDamjan Jovanovic * @see cppuhelper/defaultBootstrap_InitialComponentContext() 167*2f57578eSDamjan Jovanovic */ 168cdf0e10cSrcweir static public final XComponentContext defaultBootstrap_InitialComponentContext() 169cdf0e10cSrcweir throws Exception 170cdf0e10cSrcweir { 171cdf0e10cSrcweir return defaultBootstrap_InitialComponentContext( null, null ); 172cdf0e10cSrcweir } 173cdf0e10cSrcweir /** Bootstraps the initial component context from a native UNO installation. 174cdf0e10cSrcweir 175cdf0e10cSrcweir @param ini_file 176cdf0e10cSrcweir ini_file (may be null: uno.rc besides cppuhelper lib) 177cdf0e10cSrcweir @param bootstrap_parameters 178cdf0e10cSrcweir bootstrap parameters (maybe null) 179cdf0e10cSrcweir 180cdf0e10cSrcweir @see cppuhelper/defaultBootstrap_InitialComponentContext() 181cdf0e10cSrcweir */ 182cdf0e10cSrcweir static public final XComponentContext defaultBootstrap_InitialComponentContext( 183cdf0e10cSrcweir String ini_file, Hashtable bootstrap_parameters ) 184cdf0e10cSrcweir throws Exception 185cdf0e10cSrcweir { 186cdf0e10cSrcweir // jni convenience: easier to iterate over array than calling Hashtable 187cdf0e10cSrcweir String pairs [] = null; 188cdf0e10cSrcweir if (null != bootstrap_parameters) 189cdf0e10cSrcweir { 190cdf0e10cSrcweir pairs = new String [ 2 * bootstrap_parameters.size() ]; 191cdf0e10cSrcweir Enumeration keys = bootstrap_parameters.keys(); 192cdf0e10cSrcweir int n = 0; 193cdf0e10cSrcweir while (keys.hasMoreElements()) 194cdf0e10cSrcweir { 195cdf0e10cSrcweir String name = (String)keys.nextElement(); 196cdf0e10cSrcweir pairs[ n++ ] = name; 197cdf0e10cSrcweir pairs[ n++ ] = (String)bootstrap_parameters.get( name ); 198cdf0e10cSrcweir } 199cdf0e10cSrcweir } 200cdf0e10cSrcweir 201cdf0e10cSrcweir if (! m_loaded_juh) 202cdf0e10cSrcweir { 203cdf0e10cSrcweir NativeLibraryLoader.loadLibrary( Bootstrap.class.getClassLoader(), "juh" ); 204cdf0e10cSrcweir m_loaded_juh = true; 205cdf0e10cSrcweir } 206cdf0e10cSrcweir return UnoRuntime.queryInterface( 207cdf0e10cSrcweir XComponentContext.class, 208cdf0e10cSrcweir cppuhelper_bootstrap( 209cdf0e10cSrcweir ini_file, pairs, Bootstrap.class.getClassLoader() ) ); 210cdf0e10cSrcweir } 211cdf0e10cSrcweir 212cdf0e10cSrcweir static private boolean m_loaded_juh = false; 213cdf0e10cSrcweir static private native Object cppuhelper_bootstrap( 214cdf0e10cSrcweir String ini_file, String bootstrap_parameters [], ClassLoader loader ) 215cdf0e10cSrcweir throws Exception; 216cdf0e10cSrcweir 217cdf0e10cSrcweir /** 218cdf0e10cSrcweir * Bootstraps the component context from a UNO installation. 219cdf0e10cSrcweir * 220cdf0e10cSrcweir * @return a bootstrapped component context. 221cdf0e10cSrcweir * 222cdf0e10cSrcweir * @since UDK 3.1.0 223cdf0e10cSrcweir */ 224cdf0e10cSrcweir public static final XComponentContext bootstrap() 225cdf0e10cSrcweir throws BootstrapException { 226cdf0e10cSrcweir 227cdf0e10cSrcweir XComponentContext xContext = null; 228cdf0e10cSrcweir 229cdf0e10cSrcweir try { 230cdf0e10cSrcweir // create default local component context 231cdf0e10cSrcweir XComponentContext xLocalContext = 232cdf0e10cSrcweir createInitialComponentContext( null ); 233cdf0e10cSrcweir if ( xLocalContext == null ) 234cdf0e10cSrcweir throw new BootstrapException( "no local component context!" ); 235cdf0e10cSrcweir 236cdf0e10cSrcweir // find office executable relative to this class's class loader 237cdf0e10cSrcweir String sOffice = 238cdf0e10cSrcweir System.getProperty( "os.name" ).startsWith( "Windows" ) ? 239cdf0e10cSrcweir "soffice.exe" : "soffice"; 240cdf0e10cSrcweir File fOffice = NativeLibraryLoader.getResource( 241cdf0e10cSrcweir Bootstrap.class.getClassLoader(), sOffice ); 242cdf0e10cSrcweir if ( fOffice == null ) 243cdf0e10cSrcweir throw new BootstrapException( "no office executable found!" ); 244cdf0e10cSrcweir 245cdf0e10cSrcweir // create random pipe name 246cdf0e10cSrcweir String sPipeName = "uno" + 247cdf0e10cSrcweir Long.toString( (new Random()).nextLong() & 0x7fffffffffffffffL ); 248cdf0e10cSrcweir 249cdf0e10cSrcweir // create call with arguments 250cdf0e10cSrcweir String[] cmdArray = new String[7]; 251cdf0e10cSrcweir cmdArray[0] = fOffice.getPath(); 252cdf0e10cSrcweir cmdArray[1] = "-nologo"; 253cdf0e10cSrcweir cmdArray[2] = "-nodefault"; 254cdf0e10cSrcweir cmdArray[3] = "-norestore"; 255cdf0e10cSrcweir cmdArray[4] = "-nocrashreport"; 256cdf0e10cSrcweir cmdArray[5] = "-nolockcheck"; 257cdf0e10cSrcweir cmdArray[6] = "-accept=pipe,name=" + sPipeName + ";urp;"; 258cdf0e10cSrcweir 259cdf0e10cSrcweir // start office process 260cdf0e10cSrcweir Process p = Runtime.getRuntime().exec( cmdArray ); 261cdf0e10cSrcweir pipe( p.getInputStream(), System.out, "CO> " ); 262cdf0e10cSrcweir pipe( p.getErrorStream(), System.err, "CE> " ); 263cdf0e10cSrcweir 264cdf0e10cSrcweir // initial service manager 265cdf0e10cSrcweir XMultiComponentFactory xLocalServiceManager = 266cdf0e10cSrcweir xLocalContext.getServiceManager(); 267cdf0e10cSrcweir if ( xLocalServiceManager == null ) 268cdf0e10cSrcweir throw new BootstrapException( "no initial service manager!" ); 269cdf0e10cSrcweir 270cdf0e10cSrcweir // create a URL resolver 271cdf0e10cSrcweir XUnoUrlResolver xUrlResolver = 272cdf0e10cSrcweir UnoUrlResolver.create( xLocalContext ); 273cdf0e10cSrcweir 274cdf0e10cSrcweir // connection string 275cdf0e10cSrcweir String sConnect = "uno:pipe,name=" + sPipeName + 276cdf0e10cSrcweir ";urp;StarOffice.ComponentContext"; 277cdf0e10cSrcweir 278cdf0e10cSrcweir // wait until office is started 279cdf0e10cSrcweir for (int i = 0;; ++i) { 280cdf0e10cSrcweir try { 281cdf0e10cSrcweir // try to connect to office 282cdf0e10cSrcweir Object context = xUrlResolver.resolve( sConnect ); 283cdf0e10cSrcweir xContext = UnoRuntime.queryInterface( 284cdf0e10cSrcweir XComponentContext.class, context); 285cdf0e10cSrcweir if ( xContext == null ) 286cdf0e10cSrcweir throw new BootstrapException( "no component context!" ); 287cdf0e10cSrcweir break; 288cdf0e10cSrcweir } catch ( com.sun.star.connection.NoConnectException ex ) { 289cdf0e10cSrcweir // Wait 500 ms, then try to connect again, but do not wait 290cdf0e10cSrcweir // longer than 5 min (= 600 * 500 ms) total: 291cdf0e10cSrcweir if (i == 600) { 292cdf0e10cSrcweir throw new BootstrapException(ex.toString()); 293cdf0e10cSrcweir } 294cdf0e10cSrcweir Thread.currentThread().sleep( 500 ); 295cdf0e10cSrcweir } 296cdf0e10cSrcweir } 297cdf0e10cSrcweir } catch ( BootstrapException e ) { 298cdf0e10cSrcweir throw e; 299cdf0e10cSrcweir } catch ( java.lang.RuntimeException e ) { 300cdf0e10cSrcweir throw e; 301cdf0e10cSrcweir } catch ( java.lang.Exception e ) { 302cdf0e10cSrcweir throw new BootstrapException( e ); 303cdf0e10cSrcweir } 304cdf0e10cSrcweir 305cdf0e10cSrcweir return xContext; 306cdf0e10cSrcweir } 307cdf0e10cSrcweir 308cdf0e10cSrcweir private static void pipe( 309cdf0e10cSrcweir final InputStream in, final PrintStream out, final String prefix ) { 310cdf0e10cSrcweir 311cdf0e10cSrcweir new Thread( "Pipe: " + prefix) { 312cdf0e10cSrcweir public void run() { 313cdf0e10cSrcweir BufferedReader r = new BufferedReader( 314cdf0e10cSrcweir new InputStreamReader( in ) ); 315cdf0e10cSrcweir try { 316cdf0e10cSrcweir for ( ; ; ) { 317cdf0e10cSrcweir String s = r.readLine(); 318cdf0e10cSrcweir if ( s == null ) { 319cdf0e10cSrcweir break; 320cdf0e10cSrcweir } 321cdf0e10cSrcweir out.println( prefix + s ); 322cdf0e10cSrcweir } 323cdf0e10cSrcweir } catch ( java.io.IOException e ) { 324cdf0e10cSrcweir e.printStackTrace( System.err ); 325cdf0e10cSrcweir } 326cdf0e10cSrcweir } 327cdf0e10cSrcweir }.start(); 328cdf0e10cSrcweir } 329cdf0e10cSrcweir } 330