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