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 @throws java.lang.Exception 101 */ 102 static public XComponentContext createInitialComponentContext( Hashtable context_entries ) 103 throws Exception 104 { 105 XImplementationLoader xImpLoader = UnoRuntime.queryInterface( 106 XImplementationLoader.class, new JavaLoader() ); 107 108 // Get the factory of the ServiceManager 109 XSingleComponentFactory smgr_fac = UnoRuntime.queryInterface( 110 XSingleComponentFactory.class, xImpLoader.activate( 111 "com.sun.star.comp.servicemanager.ServiceManager", null, null, null ) ); 112 113 // Create an instance of the ServiceManager 114 XMultiComponentFactory xSMgr = UnoRuntime.queryInterface( 115 XMultiComponentFactory.class, smgr_fac.createInstanceWithContext( null ) ); 116 117 // post init loader 118 XInitialization xInit = UnoRuntime.queryInterface( 119 XInitialization.class, xImpLoader ); 120 Object[] args = new Object [] { xSMgr }; 121 xInit.initialize( args ); 122 123 // initial component context 124 if (context_entries == null) 125 context_entries = new Hashtable( 1 ); 126 // add smgr 127 context_entries.put( 128 "/singletons/com.sun.star.lang.theServiceManager", 129 new ComponentContextEntry( null, xSMgr ) ); 130 // ... xxx todo: add standard entries 131 XComponentContext xContext = new ComponentContext( context_entries, null ); 132 133 // post init smgr 134 xInit = UnoRuntime.queryInterface( 135 XInitialization.class, xSMgr ); 136 args = new Object [] { null, xContext }; // no registry, default context 137 xInit.initialize( args ); 138 139 XSet xSet = UnoRuntime.queryInterface( XSet.class, xSMgr ); 140 // insert the service manager 141 xSet.insert( smgr_fac ); 142 // and basic jurt factories 143 insertBasicFactories( xSet, xImpLoader ); 144 145 return xContext; 146 } 147 148 /** 149 * Bootstraps a servicemanager with the jurt base components registered. 150 * <p> 151 * @return a freshly boostrapped service manager 152 * @see com.sun.star.lang.ServiceManager 153 * @throws java.lang.Exception 154 */ 155 static public XMultiServiceFactory createSimpleServiceManager() throws Exception 156 { 157 return UnoRuntime.queryInterface( 158 XMultiServiceFactory.class, createInitialComponentContext( null ).getServiceManager() ); 159 } 160 161 162 /** 163 * Bootstraps the initial component context from a native UNO installation. 164 * <p> 165 * @return 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