1*d4cc1e8cSAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*d4cc1e8cSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*d4cc1e8cSAndrew Rist * or more contributor license agreements. See the NOTICE file 5*d4cc1e8cSAndrew Rist * distributed with this work for additional information 6*d4cc1e8cSAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*d4cc1e8cSAndrew Rist * to you under the Apache License, Version 2.0 (the 8*d4cc1e8cSAndrew Rist * "License"); you may not use this file except in compliance 9*d4cc1e8cSAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11*d4cc1e8cSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13*d4cc1e8cSAndrew Rist * Unless required by applicable law or agreed to in writing, 14*d4cc1e8cSAndrew Rist * software distributed under the License is distributed on an 15*d4cc1e8cSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*d4cc1e8cSAndrew Rist * KIND, either express or implied. See the License for the 17*d4cc1e8cSAndrew Rist * specific language governing permissions and limitations 18*d4cc1e8cSAndrew Rist * under the License. 19cdf0e10cSrcweir * 20*d4cc1e8cSAndrew Rist *************************************************************/ 21*d4cc1e8cSAndrew Rist 22*d4cc1e8cSAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir package com.sun.star.comp.beans; 25cdf0e10cSrcweir 26cdf0e10cSrcweir import java.awt.Container; 27cdf0e10cSrcweir import java.io.File; 28cdf0e10cSrcweir import java.util.Iterator; 29cdf0e10cSrcweir import java.util.List; 30cdf0e10cSrcweir import java.util.Vector; 31cdf0e10cSrcweir 32cdf0e10cSrcweir import com.sun.star.lang.XMultiComponentFactory; 33cdf0e10cSrcweir import com.sun.star.lang.XComponent; 34cdf0e10cSrcweir import com.sun.star.lang.XEventListener; 35cdf0e10cSrcweir import com.sun.star.connection.XConnection; 36cdf0e10cSrcweir import com.sun.star.connection.XConnector; 37cdf0e10cSrcweir import com.sun.star.bridge.XBridge; 38cdf0e10cSrcweir import com.sun.star.bridge.XBridgeFactory; 39cdf0e10cSrcweir import com.sun.star.beans.XPropertySet; 40cdf0e10cSrcweir import com.sun.star.uno.XComponentContext; 41cdf0e10cSrcweir import com.sun.star.uno.UnoRuntime; 42cdf0e10cSrcweir import com.sun.star.uno.Exception; 43cdf0e10cSrcweir import com.sun.star.lib.uno.helper.UnoUrl; 44cdf0e10cSrcweir import com.sun.star.lib.util.NativeLibraryLoader; 45cdf0e10cSrcweir 46cdf0e10cSrcweir /** 47cdf0e10cSrcweir * This class reprecents a connection to the local office application. 48cdf0e10cSrcweir * 49cdf0e10cSrcweir * @since OOo 2.0.0 50cdf0e10cSrcweir */ 51cdf0e10cSrcweir public class LocalOfficeConnection 52cdf0e10cSrcweir implements OfficeConnection 53cdf0e10cSrcweir { 54cdf0e10cSrcweir public static final String OFFICE_APP_NAME = "soffice"; 55cdf0e10cSrcweir public static final String OFFICE_LIB_NAME = "officebean"; 56cdf0e10cSrcweir public static final String OFFICE_ID_SUFFIX = "_Office"; 57cdf0e10cSrcweir 58cdf0e10cSrcweir private static String mProgramPath; 59cdf0e10cSrcweir 60cdf0e10cSrcweir private Process mProcess; 61cdf0e10cSrcweir private ContainerFactory mContainerFactory; 62cdf0e10cSrcweir private XComponentContext mContext; 63cdf0e10cSrcweir private XBridge mBridge; 64cdf0e10cSrcweir 65cdf0e10cSrcweir private String mURL; 66cdf0e10cSrcweir private String mConnType; 67cdf0e10cSrcweir private String mPipe; 68cdf0e10cSrcweir private String mPort; 69cdf0e10cSrcweir private String mProtocol; 70cdf0e10cSrcweir private String mInitialObject; 71cdf0e10cSrcweir 72cdf0e10cSrcweir private List mComponents = new Vector(); 73cdf0e10cSrcweir 74cdf0e10cSrcweir private static long m_nBridgeCounter = 0; 75cdf0e10cSrcweir //------------------------------------------------------------------------- 76cdf0e10cSrcweir static 77cdf0e10cSrcweir { 78cdf0e10cSrcweir // preload shared libraries whichs import lips are linked to officebean 79cdf0e10cSrcweir if ( System.getProperty( "os.name" ).startsWith( "Windows" ) ) 80cdf0e10cSrcweir { 81cdf0e10cSrcweir try 82cdf0e10cSrcweir { LocalOfficeConnection.class.getClassLoader()83cdf0e10cSrcweir NativeLibraryLoader.loadLibrary(LocalOfficeConnection.class.getClassLoader(), "msvcr70"); 84cdf0e10cSrcweir } 85cdf0e10cSrcweir catch (Throwable e) 86cdf0e10cSrcweir { 87cdf0e10cSrcweir // loading twice would fail 88cdf0e10cSrcweir System.err.println( "cannot find msvcr70" ); 89cdf0e10cSrcweir } 90cdf0e10cSrcweir 91cdf0e10cSrcweir try 92cdf0e10cSrcweir { LocalOfficeConnection.class.getClassLoader()93cdf0e10cSrcweir NativeLibraryLoader.loadLibrary(LocalOfficeConnection.class.getClassLoader(), "msvcr71"); 94cdf0e10cSrcweir } 95cdf0e10cSrcweir catch (Throwable e) 96cdf0e10cSrcweir { 97cdf0e10cSrcweir // loading twice would fail 98cdf0e10cSrcweir System.err.println( "cannot find msvcr71" ); 99cdf0e10cSrcweir } 100cdf0e10cSrcweir 101cdf0e10cSrcweir try 102cdf0e10cSrcweir { LocalOfficeConnection.class.getClassLoader()103cdf0e10cSrcweir NativeLibraryLoader.loadLibrary(LocalOfficeConnection.class.getClassLoader(), "uwinapi"); 104cdf0e10cSrcweir } 105cdf0e10cSrcweir catch (Throwable e) 106cdf0e10cSrcweir { 107cdf0e10cSrcweir // loading twice would fail 108cdf0e10cSrcweir System.err.println( "cannot find uwinapi" ); 109cdf0e10cSrcweir } 110cdf0e10cSrcweir 111cdf0e10cSrcweir try 112cdf0e10cSrcweir { LocalOfficeConnection.class.getClassLoader()113cdf0e10cSrcweir NativeLibraryLoader.loadLibrary(LocalOfficeConnection.class.getClassLoader(), "jawt"); 114cdf0e10cSrcweir } 115cdf0e10cSrcweir catch (Throwable e) 116cdf0e10cSrcweir { 117cdf0e10cSrcweir // loading twice would fail 118cdf0e10cSrcweir System.err.println( "cannot find jawt" ); 119cdf0e10cSrcweir } 120cdf0e10cSrcweir } 121cdf0e10cSrcweir 122cdf0e10cSrcweir // load shared library for JNI code LocalOfficeConnection.class.getClassLoader()123cdf0e10cSrcweir NativeLibraryLoader.loadLibrary( LocalOfficeConnection.class.getClassLoader(), "officebean" ); 124cdf0e10cSrcweir } 125cdf0e10cSrcweir 126cdf0e10cSrcweir //------------------------------------------------------------------------- 127cdf0e10cSrcweir // debugging method dbgPrint( String aMessage )128cdf0e10cSrcweir private void dbgPrint( String aMessage ) 129cdf0e10cSrcweir { 130cdf0e10cSrcweir System.err.println( aMessage ); 131cdf0e10cSrcweir } 132cdf0e10cSrcweir 133cdf0e10cSrcweir /** 134cdf0e10cSrcweir * Constructor. 135cdf0e10cSrcweir * Sets up paths to the office application and native libraries if 136cdf0e10cSrcweir * values are available in <code>OFFICE_PROP_FILE</code> in the user 137cdf0e10cSrcweir * home directory.<br /> 138cdf0e10cSrcweir * "com.sun.star.beans.path" - the office application directory;<br/> 139cdf0e10cSrcweir * "com.sun.star.beans.libpath" - native libraries directory. 140cdf0e10cSrcweir */ LocalOfficeConnection()141cdf0e10cSrcweir public LocalOfficeConnection() 142cdf0e10cSrcweir { 143cdf0e10cSrcweir // init member vars 144cdf0e10cSrcweir try 145cdf0e10cSrcweir { 146cdf0e10cSrcweir setUnoUrl( "uno:pipe,name=" + getPipeName() + ";urp;StarOffice.ServiceManager" ); 147cdf0e10cSrcweir } 148cdf0e10cSrcweir catch ( java.net.MalformedURLException e ) 149cdf0e10cSrcweir {} 150cdf0e10cSrcweir } 151cdf0e10cSrcweir 152cdf0e10cSrcweir /** 153cdf0e10cSrcweir * protected Constructor 154cdf0e10cSrcweir * Initialise a LocalOfficeConnection with an already running office. 155cdf0e10cSrcweir * This C'Tor is only used in complex tests at the moment. 156cdf0e10cSrcweir * @param xContext 157cdf0e10cSrcweir */ LocalOfficeConnection(com.sun.star.uno.XComponentContext xContext)158cdf0e10cSrcweir protected LocalOfficeConnection(com.sun.star.uno.XComponentContext xContext) 159cdf0e10cSrcweir { 160cdf0e10cSrcweir this.mContext = xContext; 161cdf0e10cSrcweir } 162cdf0e10cSrcweir 163cdf0e10cSrcweir /** 164cdf0e10cSrcweir * Sets a connection URL. 165cdf0e10cSrcweir * This implementation accepts a UNO URL with following format:<br /> 166cdf0e10cSrcweir * <pre> 167cdf0e10cSrcweir * url := uno:localoffice[,<params>];urp;StarOffice.ServiceManager 168cdf0e10cSrcweir * params := <path>[,<pipe>] 169cdf0e10cSrcweir * path := path=<pathv> 170cdf0e10cSrcweir * pipe := pipe=<pipev> 171cdf0e10cSrcweir * pathv := platform_specific_path_to_the_local_office_distribution 172cdf0e10cSrcweir * pipev := local_office_connection_pipe_name 173cdf0e10cSrcweir * </pre> 174cdf0e10cSrcweir * 175cdf0e10cSrcweir * @param url This is UNO URL which discribes the type of a connection. 176cdf0e10cSrcweir */ setUnoUrl(String url)177cdf0e10cSrcweir public void setUnoUrl(String url) 178cdf0e10cSrcweir throws java.net.MalformedURLException 179cdf0e10cSrcweir { 180cdf0e10cSrcweir mURL = null; 181cdf0e10cSrcweir 182cdf0e10cSrcweir String prefix = "uno:localoffice"; 183cdf0e10cSrcweir if ( url.startsWith(prefix) ) 184cdf0e10cSrcweir parseUnoUrlWithOfficePath( url, prefix ); 185cdf0e10cSrcweir else 186cdf0e10cSrcweir { 187cdf0e10cSrcweir try 188cdf0e10cSrcweir { 189cdf0e10cSrcweir UnoUrl aURL = UnoUrl.parseUnoUrl( url ); 190cdf0e10cSrcweir mProgramPath = null; 191cdf0e10cSrcweir mConnType = aURL.getConnection(); 192cdf0e10cSrcweir mPipe = (String) aURL.getConnectionParameters().get( "pipe" ); 193cdf0e10cSrcweir mPort = (String) aURL.getConnectionParameters().get( "port" ); 194cdf0e10cSrcweir mProtocol = aURL.getProtocol(); 195cdf0e10cSrcweir mInitialObject = aURL.getRootOid(); 196cdf0e10cSrcweir } 197cdf0e10cSrcweir catch ( com.sun.star.lang.IllegalArgumentException eIll ) 198cdf0e10cSrcweir { 199cdf0e10cSrcweir throw new java.net.MalformedURLException( 200cdf0e10cSrcweir "Invalid UNO connection URL."); 201cdf0e10cSrcweir } 202cdf0e10cSrcweir } 203cdf0e10cSrcweir mURL = url; 204cdf0e10cSrcweir } 205cdf0e10cSrcweir 206cdf0e10cSrcweir /** 207cdf0e10cSrcweir * Sets an AWT container catory. 208cdf0e10cSrcweir * 209cdf0e10cSrcweir * @param containerFactory This is a application provided AWT container 210cdf0e10cSrcweir * factory. 211cdf0e10cSrcweir */ setContainerFactory(ContainerFactory containerFactory)212cdf0e10cSrcweir public void setContainerFactory(ContainerFactory containerFactory) 213cdf0e10cSrcweir { 214cdf0e10cSrcweir mContainerFactory = containerFactory; 215cdf0e10cSrcweir } 216cdf0e10cSrcweir 217cdf0e10cSrcweir /** 218cdf0e10cSrcweir * Retrives the UNO component context. 219cdf0e10cSrcweir * Establishes a connection if necessary and initialises the 220cdf0e10cSrcweir * UNO service manager if it has not already been initialised. 221cdf0e10cSrcweir * This method can return <code>null</code> if it fails to connect 222cdf0e10cSrcweir * to the office application. 223cdf0e10cSrcweir * 224cdf0e10cSrcweir * @return The office UNO component context. 225cdf0e10cSrcweir */ getComponentContext()226cdf0e10cSrcweir synchronized public XComponentContext getComponentContext() 227cdf0e10cSrcweir { 228cdf0e10cSrcweir if ( mContext == null ) 229cdf0e10cSrcweir mContext = connect(); 230cdf0e10cSrcweir return mContext; 231cdf0e10cSrcweir } 232cdf0e10cSrcweir 233cdf0e10cSrcweir /** 234cdf0e10cSrcweir * Creates an office window. 235cdf0e10cSrcweir * The window is either a sub-class of java.awt.Canvas (local) or 236cdf0e10cSrcweir * java.awt.Container (RVP). 237cdf0e10cSrcweir * 238cdf0e10cSrcweir * @param container This is an AWT container. 239cdf0e10cSrcweir * @return The office window instance. 240cdf0e10cSrcweir */ createOfficeWindow(Container container)241cdf0e10cSrcweir public OfficeWindow createOfficeWindow(Container container) 242cdf0e10cSrcweir { 243cdf0e10cSrcweir return new LocalOfficeWindow(this); 244cdf0e10cSrcweir } 245cdf0e10cSrcweir 246cdf0e10cSrcweir /** 247cdf0e10cSrcweir * Closes the connection. 248cdf0e10cSrcweir */ dispose()249cdf0e10cSrcweir public void dispose() 250cdf0e10cSrcweir { 251cdf0e10cSrcweir Iterator itr = mComponents.iterator(); 252cdf0e10cSrcweir while (itr.hasNext() == true) { 253cdf0e10cSrcweir // ignore runtime exceptions in dispose 254cdf0e10cSrcweir try { ((XEventListener)itr.next()).disposing(null); } 255cdf0e10cSrcweir catch ( RuntimeException aExc ) {} 256cdf0e10cSrcweir } 257cdf0e10cSrcweir mComponents.clear(); 258cdf0e10cSrcweir 259cdf0e10cSrcweir //Terminate the bridge. It turned out that this is necessary for the bean 260cdf0e10cSrcweir //to work properly when displayed in an applet within Internet Explorer. 261cdf0e10cSrcweir //When navigating off the page which is showing the applet and then going 262cdf0e10cSrcweir //back to it, then the Java remote bridge is damaged. That is the Java threads 263cdf0e10cSrcweir //do not work properly anymore. Therefore when Applet.stop is called the connection 264cdf0e10cSrcweir //to the office including the bridge needs to be terminated. 265cdf0e10cSrcweir if (mBridge != null) 266cdf0e10cSrcweir { 267cdf0e10cSrcweir XComponent comp = (XComponent)UnoRuntime.queryInterface( 268cdf0e10cSrcweir XComponent.class, mBridge); 269cdf0e10cSrcweir if (comp != null) 270cdf0e10cSrcweir comp.dispose(); 271cdf0e10cSrcweir else 272cdf0e10cSrcweir System.err.println("LocalOfficeConnection: could not dispose bridge!"); 273cdf0e10cSrcweir 274cdf0e10cSrcweir mBridge = null; 275cdf0e10cSrcweir } 276cdf0e10cSrcweir 277cdf0e10cSrcweir mContainerFactory = null; 278cdf0e10cSrcweir mContext = null; 279cdf0e10cSrcweir } 280cdf0e10cSrcweir 281cdf0e10cSrcweir /** 282cdf0e10cSrcweir * Adds an event listener to the object. 283cdf0e10cSrcweir * 284cdf0e10cSrcweir * @param listener is a listener object. 285cdf0e10cSrcweir */ addEventListener(XEventListener listener)286cdf0e10cSrcweir public void addEventListener(XEventListener listener) 287cdf0e10cSrcweir { 288cdf0e10cSrcweir mComponents.add(listener); 289cdf0e10cSrcweir } 290cdf0e10cSrcweir 291cdf0e10cSrcweir /** 292cdf0e10cSrcweir * Removes an event listener from the listener list. 293cdf0e10cSrcweir * 294cdf0e10cSrcweir * @param listener is a listener object. 295cdf0e10cSrcweir */ removeEventListener(XEventListener listener)296cdf0e10cSrcweir public void removeEventListener(XEventListener listener) 297cdf0e10cSrcweir { 298cdf0e10cSrcweir mComponents.remove(listener); 299cdf0e10cSrcweir } 300cdf0e10cSrcweir 301cdf0e10cSrcweir /** 302cdf0e10cSrcweir * Establishes the connection to the office. 303cdf0e10cSrcweir */ connect()304cdf0e10cSrcweir private XComponentContext connect() 305cdf0e10cSrcweir { 306cdf0e10cSrcweir try 307cdf0e10cSrcweir { 308cdf0e10cSrcweir // create default local component context 309cdf0e10cSrcweir XComponentContext xLocalContext = 310cdf0e10cSrcweir com.sun.star.comp.helper.Bootstrap.createInitialComponentContext(null); 311cdf0e10cSrcweir 312cdf0e10cSrcweir // initial serviceManager 313cdf0e10cSrcweir XMultiComponentFactory xLocalServiceManager = xLocalContext.getServiceManager(); 314cdf0e10cSrcweir 315cdf0e10cSrcweir // try to connect to soffice 316cdf0e10cSrcweir Object aInitialObject = null; 317cdf0e10cSrcweir try 318cdf0e10cSrcweir { 319cdf0e10cSrcweir aInitialObject = resolve(xLocalContext, mURL); 320cdf0e10cSrcweir } 321cdf0e10cSrcweir catch( com.sun.star.connection.NoConnectException e ) 322cdf0e10cSrcweir { 323cdf0e10cSrcweir // launch soffice 324cdf0e10cSrcweir OfficeService aSOffice = new OfficeService(); 325cdf0e10cSrcweir aSOffice.startupService(); 326cdf0e10cSrcweir 327cdf0e10cSrcweir // wait until soffice is started 328cdf0e10cSrcweir long nMaxMillis = System.currentTimeMillis() + 1000*aSOffice.getStartupTime(); 329cdf0e10cSrcweir while ( aInitialObject == null ) 330cdf0e10cSrcweir { 331cdf0e10cSrcweir try 332cdf0e10cSrcweir { 333cdf0e10cSrcweir // try to connect to soffice 334cdf0e10cSrcweir Thread.currentThread().sleep( 500 ); 335cdf0e10cSrcweir aInitialObject = resolve(xLocalContext, mURL); 336cdf0e10cSrcweir } 337cdf0e10cSrcweir catch( com.sun.star.connection.NoConnectException aEx ) 338cdf0e10cSrcweir { 339cdf0e10cSrcweir // soffice did not start in time 340cdf0e10cSrcweir if ( System.currentTimeMillis() > nMaxMillis ) 341cdf0e10cSrcweir throw aEx; 342cdf0e10cSrcweir 343cdf0e10cSrcweir } 344cdf0e10cSrcweir } 345cdf0e10cSrcweir } 346cdf0e10cSrcweir finally 347cdf0e10cSrcweir { 348cdf0e10cSrcweir } 349cdf0e10cSrcweir 350cdf0e10cSrcweir // XComponentContext 351cdf0e10cSrcweir if( null != aInitialObject ) 352cdf0e10cSrcweir { 353cdf0e10cSrcweir XPropertySet xPropertySet = (XPropertySet) 354cdf0e10cSrcweir UnoRuntime.queryInterface( XPropertySet.class, aInitialObject); 355cdf0e10cSrcweir Object xContext = xPropertySet.getPropertyValue("DefaultContext"); 356cdf0e10cSrcweir XComponentContext xComponentContext = (XComponentContext) UnoRuntime.queryInterface( 357cdf0e10cSrcweir XComponentContext.class, xContext); 358cdf0e10cSrcweir return xComponentContext; 359cdf0e10cSrcweir } 360cdf0e10cSrcweir } 361cdf0e10cSrcweir catch( com.sun.star.connection.NoConnectException e ) 362cdf0e10cSrcweir { 363cdf0e10cSrcweir System.out.println( "Couldn't connect to remote server" ); 364cdf0e10cSrcweir System.out.println( e.getMessage() ); 365cdf0e10cSrcweir } 366cdf0e10cSrcweir catch( com.sun.star.connection.ConnectionSetupException e ) 367cdf0e10cSrcweir { 368cdf0e10cSrcweir System.out.println( "Couldn't access necessary local resource to establish the interprocess connection" ); 369cdf0e10cSrcweir System.out.println( e.getMessage() ); 370cdf0e10cSrcweir } 371cdf0e10cSrcweir catch( com.sun.star.lang.IllegalArgumentException e ) 372cdf0e10cSrcweir { 373cdf0e10cSrcweir System.out.println( "uno-url is syntactical illegal ( " + mURL + " )" ); 374cdf0e10cSrcweir System.out.println( e.getMessage() ); 375cdf0e10cSrcweir } 376cdf0e10cSrcweir catch( com.sun.star.uno.RuntimeException e ) 377cdf0e10cSrcweir { 378cdf0e10cSrcweir System.out.println( "--- RuntimeException:" ); 379cdf0e10cSrcweir System.out.println( e.getMessage() ); 380cdf0e10cSrcweir e.printStackTrace(); 381cdf0e10cSrcweir System.out.println( "--- end." ); 382cdf0e10cSrcweir throw e; 383cdf0e10cSrcweir } 384cdf0e10cSrcweir catch( java.lang.Exception e ) 385cdf0e10cSrcweir { 386cdf0e10cSrcweir System.out.println( "java.lang.Exception: " ); 387cdf0e10cSrcweir System.out.println( e ); 388cdf0e10cSrcweir e.printStackTrace(); 389cdf0e10cSrcweir System.out.println( "--- end." ); 390cdf0e10cSrcweir throw new com.sun.star.uno.RuntimeException( e.toString() ); 391cdf0e10cSrcweir } 392cdf0e10cSrcweir 393cdf0e10cSrcweir return null; 394cdf0e10cSrcweir } 395cdf0e10cSrcweir 396cdf0e10cSrcweir 397cdf0e10cSrcweir //The function is copied and adapted from the UrlResolver.resolve. 398cdf0e10cSrcweir //We cannot use the URLResolver because we need access to the bridge which has 399cdf0e10cSrcweir //to be disposed when Applet.stop is called. resolve(XComponentContext xLocalContext, String dcp)400cdf0e10cSrcweir private Object resolve(XComponentContext xLocalContext, String dcp) 401cdf0e10cSrcweir throws com.sun.star.connection.NoConnectException, 402cdf0e10cSrcweir com.sun.star.connection.ConnectionSetupException, 403cdf0e10cSrcweir com.sun.star.lang.IllegalArgumentException 404cdf0e10cSrcweir { 405cdf0e10cSrcweir String conDcp = null; 406cdf0e10cSrcweir String protDcp = null; 407cdf0e10cSrcweir String rootOid = null; 408cdf0e10cSrcweir 409cdf0e10cSrcweir if(dcp.indexOf(';') == -1) {// use old style 410cdf0e10cSrcweir conDcp = dcp; 411cdf0e10cSrcweir protDcp = "iiop"; 412cdf0e10cSrcweir rootOid = "classic_uno"; 413cdf0e10cSrcweir } 414cdf0e10cSrcweir else { // new style 415cdf0e10cSrcweir int index = dcp.indexOf(':'); 416cdf0e10cSrcweir String url = dcp.substring(0, index).trim(); 417cdf0e10cSrcweir dcp = dcp.substring(index + 1).trim(); 418cdf0e10cSrcweir 419cdf0e10cSrcweir index = dcp.indexOf(';'); 420cdf0e10cSrcweir conDcp = dcp.substring(0, index).trim(); 421cdf0e10cSrcweir dcp = dcp.substring(index + 1).trim(); 422cdf0e10cSrcweir 423cdf0e10cSrcweir index = dcp.indexOf(';'); 424cdf0e10cSrcweir protDcp = dcp.substring(0, index).trim(); 425cdf0e10cSrcweir dcp = dcp.substring(index + 1).trim(); 426cdf0e10cSrcweir 427cdf0e10cSrcweir rootOid = dcp.trim().trim(); 428cdf0e10cSrcweir } 429cdf0e10cSrcweir 430cdf0e10cSrcweir Object rootObject = null; 431cdf0e10cSrcweir XBridgeFactory xBridgeFactory= null; 432cdf0e10cSrcweir 433cdf0e10cSrcweir XMultiComponentFactory xLocalServiceManager = xLocalContext.getServiceManager(); 434cdf0e10cSrcweir try { 435cdf0e10cSrcweir xBridgeFactory = (XBridgeFactory)UnoRuntime.queryInterface( 436cdf0e10cSrcweir XBridgeFactory.class, 437cdf0e10cSrcweir xLocalServiceManager.createInstanceWithContext( 438cdf0e10cSrcweir "com.sun.star.bridge.BridgeFactory", xLocalContext)); 439cdf0e10cSrcweir } catch (com.sun.star.uno.Exception e) { 440cdf0e10cSrcweir throw new com.sun.star.uno.RuntimeException(e.getMessage()); 441cdf0e10cSrcweir } 442cdf0e10cSrcweir synchronized(this) { 443cdf0e10cSrcweir if(mBridge == null) { 444cdf0e10cSrcweir Object connector= null; 445cdf0e10cSrcweir try { 446cdf0e10cSrcweir connector = xLocalServiceManager.createInstanceWithContext( 447cdf0e10cSrcweir "com.sun.star.connection.Connector", xLocalContext); 448cdf0e10cSrcweir } catch (com.sun.star.uno.Exception e) { 449cdf0e10cSrcweir throw new com.sun.star.uno.RuntimeException(e.getMessage()); 450cdf0e10cSrcweir } 451cdf0e10cSrcweir XConnector connector_xConnector = (XConnector)UnoRuntime.queryInterface(XConnector.class, connector); 452cdf0e10cSrcweir // connect to the server 453cdf0e10cSrcweir XConnection xConnection = connector_xConnector.connect(conDcp); 454cdf0e10cSrcweir // create the bridge name. This should not be necessary if we pass an 455cdf0e10cSrcweir //empty string as bridge name into createBridge. Then we should always get 456cdf0e10cSrcweir //a new bridge. This does not work because of (i51323). Therefore we 457cdf0e10cSrcweir //create unique bridge names for the current process. 458cdf0e10cSrcweir String sBridgeName = "OOoBean_private_bridge_" + String.valueOf(m_nBridgeCounter++); 459cdf0e10cSrcweir try { 460cdf0e10cSrcweir mBridge = xBridgeFactory.createBridge(sBridgeName, protDcp, xConnection, null); 461cdf0e10cSrcweir } catch (com.sun.star.bridge.BridgeExistsException e) { 462cdf0e10cSrcweir throw new com.sun.star.uno.RuntimeException(e.getMessage()); 463cdf0e10cSrcweir } 464cdf0e10cSrcweir } 465cdf0e10cSrcweir rootObject = mBridge.getInstance(rootOid); 466cdf0e10cSrcweir return rootObject; 467cdf0e10cSrcweir } 468cdf0e10cSrcweir } 469cdf0e10cSrcweir 470cdf0e10cSrcweir 471cdf0e10cSrcweir /** 472cdf0e10cSrcweir * Retrives a path to the office program folder. 473cdf0e10cSrcweir * 474cdf0e10cSrcweir * @return The path to the office program folder. 475cdf0e10cSrcweir */ getProgramPath()476cdf0e10cSrcweir static private String getProgramPath() 477cdf0e10cSrcweir { 478cdf0e10cSrcweir if (mProgramPath == null) 479cdf0e10cSrcweir { 480cdf0e10cSrcweir // determine name of executable soffice 481cdf0e10cSrcweir String aExec = OFFICE_APP_NAME; // default for UNIX 482cdf0e10cSrcweir String aOS = System.getProperty("os.name"); 483cdf0e10cSrcweir 484cdf0e10cSrcweir // running on Windows? 485cdf0e10cSrcweir if (aOS.startsWith("Windows")) 486cdf0e10cSrcweir aExec = OFFICE_APP_NAME + ".exe"; 487cdf0e10cSrcweir 488cdf0e10cSrcweir // add other non-UNIX operating systems here 489cdf0e10cSrcweir // ... 490cdf0e10cSrcweir 491cdf0e10cSrcweir // find soffice executable relative to this class's class loader: 492cdf0e10cSrcweir File path = NativeLibraryLoader.getResource( 493cdf0e10cSrcweir LocalOfficeConnection.class.getClassLoader(), aExec); 494cdf0e10cSrcweir if (path != null) 495cdf0e10cSrcweir mProgramPath = path.getParent(); 496cdf0e10cSrcweir 497cdf0e10cSrcweir // default is "" 498cdf0e10cSrcweir if ( mProgramPath == null ) 499cdf0e10cSrcweir mProgramPath = ""; 500cdf0e10cSrcweir } 501cdf0e10cSrcweir return mProgramPath; 502cdf0e10cSrcweir } 503cdf0e10cSrcweir 504cdf0e10cSrcweir /** 505cdf0e10cSrcweir * Parses a connection URL. 506cdf0e10cSrcweir * This method accepts a UNO URL with following format:<br /> 507cdf0e10cSrcweir * <pre> 508cdf0e10cSrcweir * url := uno:localoffice[,<params>];urp;StarOffice.NamingService 509cdf0e10cSrcweir * params := <path>[,<pipe>] 510cdf0e10cSrcweir * path := path=<pathv> 511cdf0e10cSrcweir * pipe := pipe=<pipev> 512cdf0e10cSrcweir * pathv := platform_specific_path_to_the_local_office_distribution 513cdf0e10cSrcweir * pipev := local_office_connection_pipe_name 514cdf0e10cSrcweir * </pre> 515cdf0e10cSrcweir * 516cdf0e10cSrcweir * <h4>Examples</h4> 517cdf0e10cSrcweir * <ul> 518cdf0e10cSrcweir * <li>"uno:localoffice,pipe=xyz_Office,path=/opt/openoffice11/program;urp;StarOffice.ServiceManager"; 519cdf0e10cSrcweir * <li>"uno:socket,host=localhost,port=8100;urp;StarOffice.ServiceManager"; 520cdf0e10cSrcweir * </ul> 521cdf0e10cSrcweir * 522cdf0e10cSrcweir * @param url This is UNO URL which describes the type of a connection. 523cdf0e10cSrcweir * @exception java.net.MalformedURLException when inappropreate URL was 524cdf0e10cSrcweir * provided. 525cdf0e10cSrcweir */ parseUnoUrlWithOfficePath(String url, String prefix)526cdf0e10cSrcweir private void parseUnoUrlWithOfficePath(String url, String prefix) 527cdf0e10cSrcweir throws java.net.MalformedURLException 528cdf0e10cSrcweir { 529cdf0e10cSrcweir // Extruct parameters. 530cdf0e10cSrcweir int idx = url.indexOf(";urp;StarOffice.NamingService"); 531cdf0e10cSrcweir if (idx < 0) 532cdf0e10cSrcweir throw new java.net.MalformedURLException( 533cdf0e10cSrcweir "Invalid UNO connection URL."); 534cdf0e10cSrcweir String params = url.substring(prefix.length(), idx + 1); 535cdf0e10cSrcweir 536cdf0e10cSrcweir // Parse parameters. 537cdf0e10cSrcweir String name = null; 538cdf0e10cSrcweir String path = null; 539cdf0e10cSrcweir String pipe = null; 540cdf0e10cSrcweir char ch; 541cdf0e10cSrcweir int state = 0; 542cdf0e10cSrcweir StringBuffer buffer = new StringBuffer(); 543cdf0e10cSrcweir for(idx = 0; idx < params.length(); idx += 1) { 544cdf0e10cSrcweir ch = params.charAt(idx); 545cdf0e10cSrcweir switch (state) { 546cdf0e10cSrcweir case 0: // initial state 547cdf0e10cSrcweir switch(ch) { 548cdf0e10cSrcweir case ',': 549cdf0e10cSrcweir buffer.delete(0, buffer.length()); 550cdf0e10cSrcweir state = 1; 551cdf0e10cSrcweir break; 552cdf0e10cSrcweir 553cdf0e10cSrcweir case ';': 554cdf0e10cSrcweir state = 7; 555cdf0e10cSrcweir break; 556cdf0e10cSrcweir 557cdf0e10cSrcweir default: 558cdf0e10cSrcweir buffer.delete(0, buffer.length()); 559cdf0e10cSrcweir buffer.append(ch); 560cdf0e10cSrcweir state = 1; 561cdf0e10cSrcweir break; 562cdf0e10cSrcweir } 563cdf0e10cSrcweir break; 564cdf0e10cSrcweir 565cdf0e10cSrcweir case 1: // parameter name 566cdf0e10cSrcweir switch(ch) { 567cdf0e10cSrcweir case ' ': 568cdf0e10cSrcweir case '=': 569cdf0e10cSrcweir name = buffer.toString(); 570cdf0e10cSrcweir state = (ch == ' ')? 2: 3; 571cdf0e10cSrcweir break; 572cdf0e10cSrcweir 573cdf0e10cSrcweir case ',': 574cdf0e10cSrcweir case ';': 575cdf0e10cSrcweir state = -6; // error: invalid name 576cdf0e10cSrcweir break; 577cdf0e10cSrcweir 578cdf0e10cSrcweir default: 579cdf0e10cSrcweir buffer.append(ch); 580cdf0e10cSrcweir break; 581cdf0e10cSrcweir } 582cdf0e10cSrcweir break; 583cdf0e10cSrcweir 584cdf0e10cSrcweir case 2: // equal between the name and the value 585cdf0e10cSrcweir switch(ch) { 586cdf0e10cSrcweir case '=': 587cdf0e10cSrcweir state = 3; 588cdf0e10cSrcweir break; 589cdf0e10cSrcweir 590cdf0e10cSrcweir case ' ': 591cdf0e10cSrcweir break; 592cdf0e10cSrcweir 593cdf0e10cSrcweir default: 594cdf0e10cSrcweir state = -1; // error: missing '=' 595cdf0e10cSrcweir break; 596cdf0e10cSrcweir } 597cdf0e10cSrcweir break; 598cdf0e10cSrcweir 599cdf0e10cSrcweir case 3: // value leading spaces 600cdf0e10cSrcweir switch(ch) { 601cdf0e10cSrcweir case ' ': 602cdf0e10cSrcweir break; 603cdf0e10cSrcweir 604cdf0e10cSrcweir default: 605cdf0e10cSrcweir buffer.delete(0, buffer.length()); 606cdf0e10cSrcweir buffer.append(ch); 607cdf0e10cSrcweir state = 4; 608cdf0e10cSrcweir break; 609cdf0e10cSrcweir } 610cdf0e10cSrcweir break; 611cdf0e10cSrcweir 612cdf0e10cSrcweir case 4: // value 613cdf0e10cSrcweir switch(ch) { 614cdf0e10cSrcweir case ' ': 615cdf0e10cSrcweir case ',': 616cdf0e10cSrcweir case ';': 617cdf0e10cSrcweir idx -= 1; // put back the last read character 618cdf0e10cSrcweir state = 5; 619cdf0e10cSrcweir if (name.equals("path")) { 620cdf0e10cSrcweir if (path == null) 621cdf0e10cSrcweir path = buffer.toString(); 622cdf0e10cSrcweir else 623cdf0e10cSrcweir state = -3; // error: more then one 'path' 624cdf0e10cSrcweir } else if (name.equals("pipe")) { 625cdf0e10cSrcweir if (pipe == null) 626cdf0e10cSrcweir pipe = buffer.toString(); 627cdf0e10cSrcweir else 628cdf0e10cSrcweir state = -4; // error: more then one 'pipe' 629cdf0e10cSrcweir } else 630cdf0e10cSrcweir state = -2; // error: unknown parameter 631cdf0e10cSrcweir buffer.delete(0, buffer.length()); 632cdf0e10cSrcweir break; 633cdf0e10cSrcweir 634cdf0e10cSrcweir default: 635cdf0e10cSrcweir buffer.append(ch); 636cdf0e10cSrcweir break; 637cdf0e10cSrcweir } 638cdf0e10cSrcweir break; 639cdf0e10cSrcweir 640cdf0e10cSrcweir case 5: // a delimeter after the value 641cdf0e10cSrcweir switch(ch) { 642cdf0e10cSrcweir case ' ': 643cdf0e10cSrcweir break; 644cdf0e10cSrcweir 645cdf0e10cSrcweir case ',': 646cdf0e10cSrcweir state = 6; 647cdf0e10cSrcweir break; 648cdf0e10cSrcweir 649cdf0e10cSrcweir case ';': 650cdf0e10cSrcweir state = 7; 651cdf0e10cSrcweir break; 652cdf0e10cSrcweir 653cdf0e10cSrcweir default: 654cdf0e10cSrcweir state = -5; // error: ' ' inside the value 655cdf0e10cSrcweir break; 656cdf0e10cSrcweir } 657cdf0e10cSrcweir break; 658cdf0e10cSrcweir 659cdf0e10cSrcweir case 6: // leading spaces before next parameter name 660cdf0e10cSrcweir switch(ch) { 661cdf0e10cSrcweir case ' ': 662cdf0e10cSrcweir break; 663cdf0e10cSrcweir 664cdf0e10cSrcweir default: 665cdf0e10cSrcweir buffer.delete(0, buffer.length()); 666cdf0e10cSrcweir buffer.append(ch); 667cdf0e10cSrcweir state = 1; 668cdf0e10cSrcweir break; 669cdf0e10cSrcweir } 670cdf0e10cSrcweir break; 671cdf0e10cSrcweir 672cdf0e10cSrcweir default: 673cdf0e10cSrcweir throw new java.net.MalformedURLException( 674cdf0e10cSrcweir "Invalid UNO connection URL."); 675cdf0e10cSrcweir } 676cdf0e10cSrcweir } 677cdf0e10cSrcweir if (state != 7) 678cdf0e10cSrcweir throw new java.net.MalformedURLException( 679cdf0e10cSrcweir "Invalid UNO connection URL."); 680cdf0e10cSrcweir 681cdf0e10cSrcweir // Set up the connection parameters. 682cdf0e10cSrcweir if (path != null) 683cdf0e10cSrcweir mProgramPath = path; 684cdf0e10cSrcweir if (pipe != null) 685cdf0e10cSrcweir mPipe = pipe; 686cdf0e10cSrcweir } 687cdf0e10cSrcweir 688cdf0e10cSrcweir /* replaces each substring aSearch in aString by aReplace. 689cdf0e10cSrcweir 690cdf0e10cSrcweir StringBuffer.replaceAll() is not avaialable in Java 1.3.x. 691cdf0e10cSrcweir */ replaceAll(String aString, String aSearch, String aReplace )692cdf0e10cSrcweir private static String replaceAll(String aString, String aSearch, String aReplace ) 693cdf0e10cSrcweir { 694cdf0e10cSrcweir StringBuffer aBuffer = new StringBuffer(aString); 695cdf0e10cSrcweir 696cdf0e10cSrcweir int nPos = aString.length(); 697cdf0e10cSrcweir int nOfs = aSearch.length(); 698cdf0e10cSrcweir 699cdf0e10cSrcweir while ( ( nPos = aString.lastIndexOf( aSearch, nPos - 1 ) ) > -1 ) 700cdf0e10cSrcweir aBuffer.replace( nPos, nPos+nOfs, aReplace ); 701cdf0e10cSrcweir 702cdf0e10cSrcweir return aBuffer.toString(); 703cdf0e10cSrcweir } 704cdf0e10cSrcweir 705cdf0e10cSrcweir 706cdf0e10cSrcweir /** creates a unique pipe name. 707cdf0e10cSrcweir */ getPipeName()708cdf0e10cSrcweir static String getPipeName() 709cdf0e10cSrcweir { 710cdf0e10cSrcweir // turn user name into a URL and file system safe name (% chars will not work) 711cdf0e10cSrcweir String aPipeName = System.getProperty("user.name") + OFFICE_ID_SUFFIX; 712cdf0e10cSrcweir aPipeName = replaceAll( aPipeName, "_", "%B7" ); 713cdf0e10cSrcweir return replaceAll( replaceAll( java.net.URLEncoder.encode(aPipeName), "+", "%20" ), "%", "_" ); 714cdf0e10cSrcweir } 715cdf0e10cSrcweir 716cdf0e10cSrcweir /** 717cdf0e10cSrcweir * @para This is an implementation of the native office service. 718cdf0e10cSrcweir */ 719cdf0e10cSrcweir private class OfficeService 720cdf0e10cSrcweir implements NativeService 721cdf0e10cSrcweir { 722cdf0e10cSrcweir /** 723cdf0e10cSrcweir * Retrive the office service identifier. 724cdf0e10cSrcweir * 725cdf0e10cSrcweir * @return The identifier of the office service. 726cdf0e10cSrcweir */ getIdentifier()727cdf0e10cSrcweir public String getIdentifier() 728cdf0e10cSrcweir { 729cdf0e10cSrcweir if ( mPipe == null) 730cdf0e10cSrcweir return getPipeName(); 731cdf0e10cSrcweir else 732cdf0e10cSrcweir return mPipe; 733cdf0e10cSrcweir } 734cdf0e10cSrcweir 735cdf0e10cSrcweir /** 736cdf0e10cSrcweir * Starts the office process. 737cdf0e10cSrcweir */ startupService()738cdf0e10cSrcweir public void startupService() 739cdf0e10cSrcweir throws java.io.IOException 740cdf0e10cSrcweir { 741cdf0e10cSrcweir int nSizeCmdArray = 4; 742cdf0e10cSrcweir String sOption = null; 743cdf0e10cSrcweir //examine if user specified command-line options in system properties. 744cdf0e10cSrcweir //We may offer later a more sophisticated way of providing options if 745cdf0e10cSrcweir //the need arises. Currently this is intended to ease the pain during 746cdf0e10cSrcweir //development with pre-release builds of OOo where one wants to start 747cdf0e10cSrcweir //OOo with the -norestore options. The value of the property is simple 748cdf0e10cSrcweir //passed on to the Runtime.exec call. 749cdf0e10cSrcweir try { 750cdf0e10cSrcweir sOption = System.getProperty("com.sun.star.officebean.Options"); 751cdf0e10cSrcweir if (sOption != null) 752cdf0e10cSrcweir nSizeCmdArray ++; 753cdf0e10cSrcweir } catch (java.lang.SecurityException e) 754cdf0e10cSrcweir { 755cdf0e10cSrcweir e.printStackTrace(); 756cdf0e10cSrcweir } 757cdf0e10cSrcweir // create call with arguments 758cdf0e10cSrcweir String[] cmdArray = new String[nSizeCmdArray]; 759cdf0e10cSrcweir 760cdf0e10cSrcweir // read UNO_PATH environment variable to get path to soffice binary 761cdf0e10cSrcweir String unoPath = System.getenv("UNO_PATH"); 762cdf0e10cSrcweir if (unoPath == null) 763cdf0e10cSrcweir throw new java.io.IOException( "UNO_PATH environment variable is not set (required system path to the office program directory)" ); 764cdf0e10cSrcweir 765cdf0e10cSrcweir // cmdArray[0] = (new File(getProgramPath(), OFFICE_APP_NAME)).getPath(); 766cdf0e10cSrcweir cmdArray[0] = (new File(unoPath, OFFICE_APP_NAME)).getPath(); 767cdf0e10cSrcweir cmdArray[1] = "-nologo"; 768cdf0e10cSrcweir cmdArray[2] = "-nodefault"; 769cdf0e10cSrcweir if ( mConnType.equals( "pipe" ) ) 770cdf0e10cSrcweir cmdArray[3] = "-accept=pipe,name=" + getIdentifier() + ";" + 771cdf0e10cSrcweir mProtocol + ";" + mInitialObject; 772cdf0e10cSrcweir else if ( mConnType.equals( "socket" ) ) 773cdf0e10cSrcweir cmdArray[3] = "-accept=socket,port=" + mPort + ";urp"; 774cdf0e10cSrcweir else 775cdf0e10cSrcweir throw new java.io.IOException( "not connection specified" ); 776cdf0e10cSrcweir 777cdf0e10cSrcweir if (sOption != null) 778cdf0e10cSrcweir cmdArray[4] = sOption; 779cdf0e10cSrcweir 780cdf0e10cSrcweir // start process 781cdf0e10cSrcweir mProcess = Runtime.getRuntime().exec(cmdArray); 782cdf0e10cSrcweir if ( mProcess == null ) 783cdf0e10cSrcweir throw new RuntimeException( "cannot start soffice: " + cmdArray ); 784cdf0e10cSrcweir new StreamProcessor(mProcess.getInputStream(), System.out); 785cdf0e10cSrcweir new StreamProcessor(mProcess.getErrorStream(), System.err); 786cdf0e10cSrcweir } 787cdf0e10cSrcweir 788cdf0e10cSrcweir /** 789cdf0e10cSrcweir * Retrives the ammount of time to wait for the startup. 790cdf0e10cSrcweir * 791cdf0e10cSrcweir * @return The ammount of time to wait in seconds(?). 792cdf0e10cSrcweir */ getStartupTime()793cdf0e10cSrcweir public int getStartupTime() 794cdf0e10cSrcweir { 795cdf0e10cSrcweir return 60; 796cdf0e10cSrcweir } 797cdf0e10cSrcweir } 798cdf0e10cSrcweir 799cdf0e10cSrcweir 800cdf0e10cSrcweir 801cdf0e10cSrcweir class StreamProcessor extends Thread 802cdf0e10cSrcweir { 803cdf0e10cSrcweir java.io.InputStream m_in; 804cdf0e10cSrcweir java.io.PrintStream m_print; 805cdf0e10cSrcweir StreamProcessor(final java.io.InputStream in, final java.io.PrintStream out)806cdf0e10cSrcweir public StreamProcessor(final java.io.InputStream in, final java.io.PrintStream out) 807cdf0e10cSrcweir { 808cdf0e10cSrcweir m_in = in; 809cdf0e10cSrcweir m_print = out; 810cdf0e10cSrcweir start(); 811cdf0e10cSrcweir } 812cdf0e10cSrcweir run()813cdf0e10cSrcweir public void run() { 814cdf0e10cSrcweir java.io.BufferedReader r = new java.io.BufferedReader( 815cdf0e10cSrcweir new java.io.InputStreamReader(m_in) ); 816cdf0e10cSrcweir try { 817cdf0e10cSrcweir for ( ; ; ) { 818cdf0e10cSrcweir String s = r.readLine(); 819cdf0e10cSrcweir if ( s == null ) { 820cdf0e10cSrcweir break; 821cdf0e10cSrcweir } 822cdf0e10cSrcweir m_print.println(s); 823cdf0e10cSrcweir } 824cdf0e10cSrcweir } catch ( java.io.IOException e ) { 825cdf0e10cSrcweir e.printStackTrace( System.err ); 826cdf0e10cSrcweir } 827cdf0e10cSrcweir } 828cdf0e10cSrcweir } 829cdf0e10cSrcweir 830cdf0e10cSrcweir } 831