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