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