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