xref: /trunk/main/bean/java/officebean/src/main/java/com/sun/star/comp/beans/OOoBean.java (revision 6fd2419af095b9e12baf06e33db2129edf4d719b)
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 com.sun.star.uno.UnoRuntime;
27 
28 // @requirement FUNC.PERF.LRN/0.6
29 // @requirement FUNC.PERF.LOC/0.6
30 // @requirement FUNC.PERF.FIX/0.6
31 /** This is the basic JavaBean for all AOO application modules.
32 
33     @requirement FUNC.RES.OTH/0.2
34         No other resources are needed yet.
35 
36     @since OOo 2.0.0
37  */
38 public class OOoBean
39 
40     // @requirement FUNC.BEAN.VIEW/0.4
41     extends java.awt.Container
42 
43     implements
44         // @requirement FUNC.PER/0.2
45         java.io.Externalizable
46 {
47     // timeout values (milliseconds)
48     int nOOoStartTimeOut = 60000;
49     int nOOoCallTimeOut =   3000;
50     int nOOoCheckCycle =    1000;
51 
52     // This member contains the connection to an AOO instance if established.
53     private transient OfficeConnection      iConnection;
54     private transient EventListener         xConnectionListener;
55 
56     // @requirement FUNC.BEAN.VIEW/0.4
57     // @requirement FUNC.BEAN.EDIT/0.4
58     // This member contains the AOO window
59     // if a connection is established.
60     // It is a child of the OOoBean canvas.
61     private OfficeWindow xFrameWindow;
62 
63     // application environment
64     private transient com.sun.star.lang.XMultiServiceFactory xServiceFactory;
65     private transient com.sun.star.frame.XDesktop xDesktop;
66 
67     // document and frame
68     private transient Frame aFrame;
69     private transient Controller aController;
70     private transient OfficeDocument aDocument;
71 
72     // slot command execution environment
73     private transient com.sun.star.frame.XDispatchProvider xDispatcher;
74     private transient com.sun.star.util.XURLTransformer xURLTransformer;
75 
76     // properties
77     private boolean bIgnoreVisibility = false; // to show even if already visible
78     private boolean bMenuBarVisible = true;
79     private boolean bStandardBarVisible = true;
80     private boolean bToolBarVisible = true;
81     private boolean bStatusBarVisible = true;
82 
83     // debugging method
dbgPrint( String aMessage )84     private void dbgPrint( String aMessage )
85     {
86         // System.err.println( "OOoBean: " + aMessage );
87     }
88 
89     // @requirement FUNC.PER/0.2
90     /** @internal
91      *  @deprecated
92      */
writeExternal( java.io.ObjectOutput aObjOut )93     public void writeExternal( java.io.ObjectOutput aObjOut )
94     {
95         // TBD
96     }
97 
98     // @requirement FUNC.PER/0.2
99     /** @internal
100      *  @deprecated
101      */
readExternal( java.io.ObjectInput aObjIn )102     public void readExternal( java.io.ObjectInput aObjIn )
103     {
104         // TBD
105     }
106 
107     /** Generic constructor of the OOoBean.
108 
109         Neither a connection is established nor any document loaded.
110      */
OOoBean()111     public OOoBean()
112     {}
113 
114     // @requirement FUNC.CON.MULT/0.3
115     /** Constructor for an OOoBean which uses a specific office connection.
116 
117         The connection must be established but no document is loaded.
118 
119         @throws NoConnectionException
120             if the connection is not established.
121 
122         @deprecated Clients could use the getOOoConnection to obtain an OfficeConnection
123         and use it as argument in a constructor for another OOoBean instance. Calling
124         the dispose method of the OfficeConnection or the OOoBean's stopOOoConnection
125         method would make all instances of OOoBean stop working.
126      */
OOoBean( OfficeConnection iConnection )127     public OOoBean( OfficeConnection iConnection )
128         throws NoConnectionException
129     {
130         try { setOOoConnection( iConnection ); }
131         catch ( HasConnectionException aExc )
132         { /* impossible here */ }
133     }
134 
135     /** Sets the timeout for methods which launch AOO in milliseconds.
136 
137         This method does not need a connection to an AOO instance.
138      */
setOOoStartTimeOut( int nMilliSecs )139     public void setOOoStartTimeOut( int nMilliSecs )
140     {
141         nOOoStartTimeOut = nMilliSecs;
142     }
143 
144     /** Sets the timeout for normal AOO methods calls in milliseconds.
145 
146         This method does not need a connection to an AOO instance.
147      */
setOOoCallTimeOut( int nMilliSecs )148     public void setOOoCallTimeOut( int nMilliSecs )
149     {
150         nOOoCallTimeOut = nMilliSecs;
151     }
152 
153     /** Sets the period length in milliseconds to check the AOO connection.
154 
155         This method does not need a connection to an AOO instance.
156      */
setOOoCheckCycle( int nMilliSecs )157     public void setOOoCheckCycle( int nMilliSecs )
158     {
159         nOOoCheckCycle = nMilliSecs;
160     }
161 
162     /** Sets the a connection to an AOO instance.
163 
164         @internal
165      */
setOOoConnection( OfficeConnection iNewConnection )166     private synchronized void setOOoConnection( OfficeConnection iNewConnection )
167         throws  HasConnectionException, NoConnectionException
168     {
169         // the connection cannot be exchanged
170         if ( iConnection != null )
171             throw new HasConnectionException();
172 
173         // is there a real connection, not just the proxy?
174         com.sun.star.uno.XComponentContext xComponentContext = null;
175         try { xComponentContext = iNewConnection.getComponentContext(); }
176         catch ( java.lang.Throwable aExc )
177         { throw new NoConnectionException(); }
178         if ( xComponentContext == null )
179             throw new NoConnectionException();
180 
181         // set the connection
182         iConnection = iNewConnection;
183 
184         // get notified when connection dies
185         if ( xConnectionListener != null )
186             xConnectionListener.end();
187         xConnectionListener = this.new EventListener("setOOoConnection");
188     }
189 
190     // @requirement FUNC.CON.STRT/0.4
191     /** Starts a connection to an AOO instance which is launched if not running.
192 
193         @throws HasConnectionException
194             if a connection was already established.
195 
196         @throws NoConnectionException
197             if the specified connection cannot be established
198      */
startOOoConnection( String aConnectionURL )199     public void startOOoConnection( String aConnectionURL )
200         throws  java.net.MalformedURLException,
201             HasConnectionException,
202             NoConnectionException
203     {
204         // create a new connection from the given connection URL
205         LocalOfficeConnection aConnection = new LocalOfficeConnection();
206         aConnection.setUnoUrl( aConnectionURL );
207         setOOoConnection( aConnection );
208     }
209 
210     // @requirement FUNC.CON.CHK/0.7
211     /** Returns true if this OOoBean is connected to an AOO instance,
212         false otherwise.
213 
214         @deprecated This method is not useful in a multithreaded environment. Then
215         all threads accessing the instance would have to be synchronized in order to
216         make is method work. It is better
217         to call OOoBean's methods and be prepared to catch a NoConnectionException.
218      */
isOOoConnected()219     public boolean isOOoConnected()
220     {
221         return iConnection != null;
222     }
223 
224     // @requirement FUNC.CON.STOP/0.4
225     /** Disconnects from the connected AOO instance.
226 
227         If there was no connection yet or anymore, this method can be called
228         anyway.
229 
230         When the OOoBean is displayed in an applet by a web browser, then this
231         method must be called from within java.applet.Applet.stop.
232      */
stopOOoConnection()233     public synchronized void stopOOoConnection()
234     {
235         // clear AOO document, frame etc.
236         clear();
237 
238         // cut the connection
239         OfficeConnection iExConnection = iConnection;
240         if ( iConnection != null )
241         {
242             if ( xConnectionListener != null )
243             {
244                 xConnectionListener.end();
245             }
246             iConnection = null;
247             iExConnection.dispose();
248         }
249 
250     }
251 
252     // @requirement FUNC.CON.STOP/0.4 (via XComponent.dispose())
253     // @requirement FUNC.CON.NTFY/0.4 (via XComponent.addEventListener())
254     /** Returns the a connection to an AOO instance.
255 
256         If no connection exists, a default connection will be created. An OfficeConnection
257         can be used to register listeners of type com.sun.star.lang.EventListener,
258         which are notified when the connection to the
259         office dies. One should not call the dispose method, because this may result
260         in receiving com.sun.star.lang.DisposedExceptions when calling
261         {@link #stopOOoConnection stopOOoConnection} or other API methods. If other instances share the
262         same connection then they will stop function properly, because they loose their
263         connection as well. The recommended way to end the connection is
264         calling {@link #stopOOoConnection stopOOoConnection}.
265 
266         @throws NoConnectionException
267             if no connection can be established
268 
269      */
getOOoConnection()270     public synchronized OfficeConnection getOOoConnection()
271         throws NoConnectionException
272     {
273         if ( iConnection == null )
274         {
275             try { setOOoConnection( new LocalOfficeConnection() ); }
276             catch ( HasConnectionException aExc )
277             { /* impossible here */ }
278         }
279         if ( iConnection.getComponentContext() == null )
280             throw new NoConnectionException();
281         return iConnection;
282     }
283 
284     /** Returns the service factory used by this OOoBean instance.
285 
286         @throws NoConnectionException
287             if no connection is established and no default connection can be established.
288      */
getMultiServiceFactory()289     public synchronized com.sun.star.lang.XMultiServiceFactory getMultiServiceFactory()
290         throws NoConnectionException
291     {
292         if ( xServiceFactory == null )
293         {
294             // avoid concurrent access from multiple threads
295             final OfficeConnection iConn = getOOoConnection();
296 
297             Thread aConnectorThread = new Thread() {
298                 public void run()
299                 {
300                     com.sun.star.lang.XMultiComponentFactory aFactory =
301                         iConn.getComponentContext().getServiceManager();
302                     xServiceFactory = (com.sun.star.lang.XMultiServiceFactory)
303                         UnoRuntime.queryInterface(
304                             com.sun.star.lang.XMultiServiceFactory.class, aFactory );
305                 }
306             };
307             aConnectorThread.start();
308             try { aConnectorThread.join(nOOoStartTimeOut); }
309             catch ( java.lang.InterruptedException aExc )
310             { throw new NoConnectionException(); }
311             if ( xServiceFactory == null )
312                 throw new NoConnectionException();
313         }
314 
315         return xServiceFactory;
316     }
317 
318     /** Returns the XDesktop interface of the AOO instance used by this OOoBean.
319 
320         @throws NoConnectionException
321             if no connection is established and no default connection can be established.
322      */
getOOoDesktop()323     public synchronized com.sun.star.frame.XDesktop getOOoDesktop()
324         throws NoConnectionException
325     {
326         if ( xDesktop == null )
327         {
328             try
329             {
330                 Object aObject = getMultiServiceFactory().createInstance( "com.sun.star.frame.Desktop");
331                 xDesktop = (com.sun.star.frame.XDesktop) UnoRuntime.queryInterface(
332                         com.sun.star.frame.XDesktop.class, aObject );
333             }
334             catch ( com.sun.star.uno.Exception aExc )
335             {} // TBD: what if no connection exists?
336         }
337 
338         return xDesktop;
339     }
340 
341     /** Resets this bean to an empty document.
342 
343         If a document is loaded and the content modified,
344         the changes are dismissed. Otherwise nothing happens.
345 
346         This method is intended to be overridden in derived classes.
347         This implementation simply calls clear.
348 
349         @param bClearStateToo
350         Not only the document content but also the state of the bean,
351         like visibility of child components is cleared.
352 
353         @deprecated There is currently no way to dismiss changes, except for loading
354         of the unchanged initial document. Furthermore it is unclear how derived classes
355         handle this and what exactly their state is (e.g. what members make up their state).
356         Calling this method on a derived class requires knowledge about their implementation.
357         Therefore a deriving class should declare their own clearDocument if needed. Clients
358         should call the clearDocument of the deriving class or {@link #clear} which discards
359         the currently displayed document.
360      */
clearDocument( boolean bClearStateToo )361     public synchronized void clearDocument( boolean bClearStateToo )
362         throws
363             com.sun.star.util.CloseVetoException,
364             NoConnectionException
365     {
366         // TBD
367         clear();
368     }
369 
370     /** Resets the OOoBean to an empty status.
371 
372         Any loaded document is unloaded, no matter whether it is modified or not.
373         After calling this method, the OOoBean has no office document and no frame
374         anymore. The connection will stay, though.
375 
376         This method works with or without an established connection.
377      */
clear()378     public synchronized void clear()
379     {
380         dbgPrint( "clear()" );
381 
382         try
383         {
384             CallWatchThread aCallWatchThread =
385                 new CallWatchThread( nOOoCallTimeOut, "clear" );
386             // By closing the frame we avoid that dialogs are displayed, for example when
387             // the document is modified.
388             com.sun.star.util.XCloseable xCloseable = (com.sun.star.util.XCloseable)
389                 UnoRuntime.queryInterface( com.sun.star.util.XCloseable.class, aFrame );
390             if ( xCloseable != null )
391             {
392                 try
393                 {
394                     xCloseable.close(true);
395                 }
396                 catch (com.sun.star.util.CloseVetoException exc)
397                 { // a print job may be running
398                 }
399             }
400 
401             aDocument = null;
402             xDispatcher = null;
403             aFrame = null;
404 
405             // clear xFrameWindow
406             if ( xFrameWindow != null )
407             {
408                 try { releaseSystemWindow(); }
409                 catch ( NoConnectionException aExc )
410                 {} // ignore
411                 catch ( SystemWindowException aExc )
412                 {} // ignore
413                 remove( xFrameWindow.getAWTComponent() );
414                 xFrameWindow = null;
415             }
416 
417             // clear xURTTransformer
418             if ( xURLTransformer != null )
419             {
420                 try
421                 {
422                     com.sun.star.lang.XComponent xComp = (com.sun.star.lang.XComponent)
423                         UnoRuntime.queryInterface(
424                             com.sun.star.lang.XComponent.class, xURLTransformer );
425                     if ( xComp != null )
426                         xComp.dispose();
427                 }
428                 catch ( java.lang.Throwable aExc )
429                 {} // ignore
430                 xURLTransformer = null;
431             }
432 
433             xDesktop = null;
434             xServiceFactory = null;
435 
436             aCallWatchThread.cancel();
437         }
438         catch ( java.lang.InterruptedException aExc )
439         { /* can be ignored */ }
440     }
441 
442     // @requirement FUNC.PAR.LWP/0.4
443     /** This method causes the office window to be displayed.
444 
445         If no document is loaded and the instance is added to a Java container that
446         is showing, then this method needs not to be called. If later one of the methods
447         {@link #loadFromURL loadFromURL}, {@link #loadFromStream loadFromStream1},
448         or {@link #loadFromByteArray loadFromByteArray}
449         is called, then the document is automatically displayed.
450 
451         Should one of the load methods have been called before the Java container
452         was showing, then this method needs to be called after the container window
453         was made visible (java.lang.Component.setVisible(true)).
454         <p>
455         Another scenario is that a OOoBean contains a document and is removed
456         from a Java container and later added again. Then aquireSystemWindow needs
457         to be called after the container window is displayed.
458 
459         @throws SystemWindowException
460             if no system window can be acquired.
461 
462         @throws NoConnectionException
463             if the connection is not established.
464      */
aquireSystemWindow()465     public synchronized void aquireSystemWindow()
466         throws
467             SystemWindowException,
468 
469             // @requirement FUNC.CON.LOST/0.2
470             NoConnectionException
471     {
472         if ( iConnection == null )
473             throw new NoConnectionException();
474         if ( !isShowing() )
475             throw new SystemWindowException();
476 
477         if ( xFrameWindow != null )
478             xFrameWindow.getAWTComponent().setVisible(true);
479         doLayout();
480     }
481 
482     // @requirement FUNC.PAR.RWL/0.4
483     // @estimation 16h
484     /** This method must be called when the OOoBean before the
485         system window may be released by it's parent AWT/Swing component.
486 
487         This is the case when java.awt.Component.isDisplayable() returns
488         true. This is definitely the case when the OOoBean is removed
489         from it's parent container.
490 
491         @throws SystemWindowException
492         if system window is not acquired.
493 
494         @throws NoConnectionException
495         if the connection is not established.
496 
497         @deprecated When Component.removeNotify of the parent window of the actual
498         office window is called, then the actions are performed for which this method
499         needed to be called previously.
500      */
releaseSystemWindow()501     public synchronized void releaseSystemWindow()
502         throws
503             SystemWindowException,
504 
505             // @requirement FUNC.CON.LOST/0.2
506             NoConnectionException
507     {
508         if ( iConnection == null )
509             throw new NoConnectionException();
510 
511         try { xFrameWindow.getAWTComponent().setVisible(false); }
512         catch ( com.sun.star.lang.DisposedException aExc )
513         { throw new NoConnectionException(); }
514     }
515 
516     // @requirement FUNC.BEAN.LOAD/0.4
517     // @requirement FUNC.CON.AUTO/0.3
518     /** Loads the bean from the given URL.
519 
520         If a document is already loaded and the content modified,
521         the changes are dismissed.
522 
523         If no connection exists, a default connection is established.
524 
525         @throws IllegalArgumentException
526             if either of the arguments is out of the specified range.
527 
528         @throws java.io.IOException
529             if an IO error occurs reading the resource specified by the URL.
530 
531         @throws com.sun.star.lang.NoConnectionException
532             if no connection can be established.
533 
534         @throws com.sun.star.util.CloseVetoException
535             if the currently displayed document cannot be closed because it is
536             still be used, for example it is printed.
537      */
loadFromURL( final String aURL, final com.sun.star.beans.PropertyValue aArguments[] )538     public void loadFromURL(
539             final String aURL,
540             final com.sun.star.beans.PropertyValue aArguments[] )
541         throws
542             // @requirement FUNC.CON.LOST/0.2
543             NoConnectionException,
544             java.io.IOException,
545             com.sun.star.lang.IllegalArgumentException,
546             com.sun.star.util.CloseVetoException
547     {
548         dbgPrint( "loadFromURL()" );
549         // try loading
550         try
551         {
552             boolean bLoaded = false;
553             while ( !bLoaded )
554             {
555                 // watch loading in a thread with a timeout (if AOO hangs)
556                 CallWatchThread aCallWatchThread =
557                     new CallWatchThread( nOOoStartTimeOut, "loadFromURL" );
558 
559                 try
560                 {
561                     // get window from AOO on demand
562                     if ( xFrameWindow == null )
563                     {
564                         // Establish the connection by request of the ServiceFactory.
565                         getMultiServiceFactory();
566 
567                         // remove existing child windows
568                         removeAll();
569 
570                         // Create the OfficeWindow.
571                         xFrameWindow = getOOoConnection().createOfficeWindow(OOoBean.this);
572                         add( xFrameWindow.getAWTComponent() );
573                     }
574 
575                     // create the document frame from UNO window.
576                     if ( aFrame == null )
577                     {
578                         // create the frame
579                         com.sun.star.awt.XWindow xWindow =
580                             (com.sun.star.awt.XWindow) UnoRuntime.queryInterface(
581                             com.sun.star.awt.XWindow.class, xFrameWindow.getUNOWindowPeer());
582                         Object xFrame = xServiceFactory.createInstance( "com.sun.star.frame.Frame");
583                         aFrame = new Frame( (com.sun.star.frame.XFrame)UnoRuntime.queryInterface(
584                                 com.sun.star.frame.XFrame.class, xFrame ) );
585                         aFrame.initialize( xWindow );
586                         aFrame.setName( aFrame.toString() );
587 
588                         // register the frame at the desktop
589                         com.sun.star.frame.XFrames xFrames =
590                                 ( (com.sun.star.frame.XFramesSupplier)UnoRuntime.queryInterface(
591                                 com.sun.star.frame.XFramesSupplier.class, getOOoDesktop() ) ).getFrames();
592                         xFrames.append( aFrame );
593                     }
594 
595                     // Initializes the slot command execution environment.
596                     xURLTransformer = (com.sun.star.util.XURLTransformer) UnoRuntime.queryInterface(
597                         com.sun.star.util.XURLTransformer.class,
598                         xServiceFactory.createInstance( "com.sun.star.util.URLTransformer") );
599 
600                                         try
601                                         {
602                                             xDispatcher = UnoRuntime.queryInterface(com.sun.star.frame.XDispatchProvider.class, aFrame);
603                                         }
604                                         catch (Exception e)
605                                         {
606                                             /* ignore! */
607                                         }
608 
609                     // get XComponentLoader from frame
610                     com.sun.star.frame.XComponentLoader xLoader = (com.sun.star.frame.XComponentLoader)
611                         UnoRuntime.queryInterface( com.sun.star.frame.XComponentLoader.class, aFrame );
612                     if ( xLoader == null )
613                     {
614                         throw new java.lang.RuntimeException(
615                             "com.sun.star.frame.Frame(" + aFrame +
616                                 ") without com.sun.star.frame.XComponentLoader" );
617                     }
618 
619                     // Avoid Dialog 'Document changed' while reloading
620                     if ( aDocument != null )
621                     {
622                         try {
623                             aDocument.setModified(false);
624                         } catch (com.sun.star.beans.PropertyVetoException ep) {
625                             // it doesn't make sense to throw the exception here. The interface does not
626                             // offer a way to add/remove respective listeners.
627                         } catch (com.sun.star.lang.DisposedException ed) {
628                             // can be disposed if user closed document via UI
629                         }
630 
631                         com.sun.star.frame.XController xOldController = null;
632                         if ( aFrame != null )
633                             xOldController = aFrame.getController();
634 
635                         try
636                         {
637 
638                             if ( aFrame != null && xOldController != null )
639                                 if (xOldController.suspend(true) == false)
640                                     throw new com.sun.star.util.CloseVetoException(
641                                             "Document is still being used and cannot be closed.", this);
642 
643                         }
644                         catch (java.lang.IllegalStateException exp)
645                         {}
646                     }
647 
648                     // load the document.
649                     com.sun.star.beans.PropertyValue aArgs[] =
650                         addArgument( aArguments, new com.sun.star.beans.PropertyValue(
651                             "MacroExecutionMode", -1,
652                             com.sun.star.document.MacroExecMode.USE_CONFIG,
653                             com.sun.star.beans.PropertyState.DIRECT_VALUE ) );
654                                     //String fn = aFRame.getName();
655 
656                     com.sun.star.lang.XComponent xComponent = xLoader.loadComponentFromURL(
657                         aURL, /*aFrame.getName()*/"_self", 0, aArgs );
658 
659                     // nothing loaded?
660                     if ( xComponent == null && aDocument != null )
661                     {
662                         // reactivate old document
663                         if ( aFrame != null && aFrame.getController() != null )
664                             aFrame.getController().suspend(false);
665                         aDocument.setModified(true);
666 
667                         // throw exception
668                         throw new java.io.IOException(
669                             "Can not load a document: \"" + aURL + "\"");
670                     }
671                     // mDocumentURL = aURL; TBD: still needed?
672 
673                     // Get document's XModifiable interface if any.
674                     aDocument = new OfficeDocument(
675                         (com.sun.star.frame.XModel) UnoRuntime.queryInterface(
676                         com.sun.star.frame.XModel.class, xComponent ) );
677                     bLoaded = true;
678                 }
679                 catch ( NoConnectionException aExc )
680                 {
681                     // stop, clear and retry
682                     stopOOoConnection();
683                 }
684                 catch ( com.sun.star.lang.DisposedException aExc )
685                 {
686                     // stop, clear and retry
687                     stopOOoConnection();
688                 }
689                 catch ( com.sun.star.uno.Exception aExc )
690                 {
691                     // TDB: handling failure in createInstance
692                     aExc.printStackTrace();
693                     throw new java.io.IOException();
694                 }
695 
696                 aCallWatchThread.cancel();
697                 if ( xServiceFactory == null )
698                     throw new NoConnectionException();
699             }
700             if ( iConnection == null )
701             {
702                 throw new NoConnectionException();
703             }
704 
705             applyToolVisibilities();
706         }
707         catch ( java.lang.InterruptedException aExc )
708         {
709             throw new NoConnectionException();
710         }
711     }
712 
713     /** Loads a document from a Java stream.
714 
715         See loadFromURL() for further information.
716      */
loadFromStream( final java.io.InputStream iInStream, final com.sun.star.beans.PropertyValue aArguments[] )717     public void loadFromStream(
718             final java.io.InputStream iInStream,
719             final com.sun.star.beans.PropertyValue aArguments[] )
720         throws
721             // @requirement FUNC.CON.LOST/0.2
722             NoConnectionException,
723             java.io.IOException,
724             com.sun.star.lang.IllegalArgumentException,
725             com.sun.star.util.CloseVetoException
726     {
727         // wrap Java stream into UNO stream
728                  /*
729         com.sun.star.io.XInputStream xStream =
730                 new com.sun.star.lib.uno.adapter.InputStreamToXInputStreamAdapter(
731                     iInStream );
732                  */
733                  // copy stream...
734 
735                 int s = 4096;
736                 int r=0 ,n = 0;
737                 byte[] buffer = new byte[s];
738                 byte[] newBuffer = null;
739                 while ((r = iInStream.read(buffer, n, buffer.length-n))>0) {
740                     n += r;
741                     if (iInStream.available() > buffer.length - n) {
742                         newBuffer = new byte[buffer.length*2];
743                         System.arraycopy(buffer, 0, newBuffer, 0, n);
744                         buffer = newBuffer;
745                     }
746                 }
747                 if (buffer.length != n) {
748                     newBuffer = new byte[n];
749                     System.arraycopy(buffer, 0, newBuffer, 0, n);
750                     buffer = newBuffer;
751                 }
752                 com.sun.star.io.XInputStream xStream =
753                     new com.sun.star.lib.uno.adapter.ByteArrayToXInputStreamAdapter(buffer);
754 
755         // add stream to arguments
756         com.sun.star.beans.PropertyValue[] aExtendedArguments =
757             addArgument( aArguments, new com.sun.star.beans.PropertyValue(
758                 "InputStream", -1, xStream, com.sun.star.beans.PropertyState.DIRECT_VALUE ) );
759 
760         // call normal load method
761         loadFromURL( "private:stream", aExtendedArguments );
762     }
763 
764     /** Loads a document from a byte array.
765 
766         See loadFromURL() for further information.
767      */
loadFromByteArray( final byte aInBuffer[], final com.sun.star.beans.PropertyValue aArguments[] )768     public void loadFromByteArray(
769             final byte aInBuffer[],
770             final com.sun.star.beans.PropertyValue aArguments[] )
771         throws
772             // @requirement FUNC.CON.LOST/0.2
773             NoConnectionException,
774             java.io.IOException,
775             com.sun.star.lang.IllegalArgumentException,
776             com.sun.star.util.CloseVetoException
777     {
778         // wrap byte array into UNO stream
779         com.sun.star.io.XInputStream xStream =
780                 new com.sun.star.lib.uno.adapter.ByteArrayToXInputStreamAdapter(
781                     aInBuffer );
782 
783         // add stream to arguments
784         com.sun.star.beans.PropertyValue[] aExtendedArguments =
785             addArgument( aArguments, new com.sun.star.beans.PropertyValue(
786                 "InputStream", -1, xStream, com.sun.star.beans.PropertyState.DIRECT_VALUE ) );
787 
788         // call normal load method
789         loadFromURL( "private:stream", aExtendedArguments );
790     }
791 
792     /** Stores a document to the given URL.
793         <p>
794         Due due a bug (50651) calling this method may cause the office to crash,
795         when at the same time the office writes a backup of the document. This bug
796         also affects {@link #storeToByteArray storeToByteArray} and
797         {@link #storeToStream storeToStream}. The workaround
798         is to start the office with the option -norestore, which disables the automatic
799         backup and recovery mechanism. OOoBean offers currently no supported way of providing
800         startup options for AOO. But it is possible to set a Java property when starting
801         Java, which is examined by OOoBean:
802         <pre>
803             java -Dcom.sun.star.officebean.Options=-norestore ...
804         </pre>
805         It is planned to offer a way of specifying startup options in a future version.
806         The property can be used until then. When using this property only one option
807         can be provided.
808 
809         @throws IllegalArgumentException
810             if either of the arguments is out of the specified range.
811 
812         @throws java.io.IOException
813             if an IO error occurs reading the resource specified by the URL.
814 
815         @throws com.sun.star.lang.NoConnectionException
816             if no connection is established.
817 
818         @throws NoDocumentException
819             if no document is loaded
820      */
storeToURL( final String aURL, final com.sun.star.beans.PropertyValue aArguments[] )821     public void storeToURL(
822             final String aURL,
823             final com.sun.star.beans.PropertyValue aArguments[] )
824         throws
825             // @requirement FUNC.CON.LOST/0.2
826             NoConnectionException,
827             java.io.IOException,
828             com.sun.star.lang.IllegalArgumentException,
829             NoDocumentException
830     {
831         // no document available?
832         if ( aDocument == null )
833             throw new NoDocumentException();
834 
835         try
836         {
837             // start runtime timeout
838             CallWatchThread aCallWatchThread =
839                 new CallWatchThread( nOOoCallTimeOut, "storeToURL" );
840 
841             // store the document
842             try { aDocument.storeToURL( aURL, aArguments ); }
843             catch ( com.sun.star.io.IOException aExc )
844             { throw new java.io.IOException(); }
845 
846             // end runtime timeout
847             aCallWatchThread.cancel();
848         }
849         catch ( java.lang.InterruptedException aExc )
850         { throw new NoConnectionException(); }
851     }
852 
853     /** Stores a document to a stream.
854 
855         See {@link #storeToURL storeToURL} for further information.
856         @see #storeToURL storeToURL
857      */
storeToStream( java.io.OutputStream aOutStream, final com.sun.star.beans.PropertyValue aArguments[] )858     public java.io.OutputStream storeToStream(
859             java.io.OutputStream aOutStream,
860             final com.sun.star.beans.PropertyValue aArguments[] )
861         throws
862             // @requirement FUNC.CON.LOST/0.2
863             NoConnectionException,
864             NoDocumentException,
865             java.io.IOException,
866             com.sun.star.lang.IllegalArgumentException
867 
868     {
869         // wrap Java stream into UNO stream
870         com.sun.star.lib.uno.adapter.OutputStreamToXOutputStreamAdapter aStream =
871                 new com.sun.star.lib.uno.adapter.OutputStreamToXOutputStreamAdapter(
872                     aOutStream );
873 
874         // add stream to arguments
875         com.sun.star.beans.PropertyValue[] aExtendedArguments =
876             addArgument( aArguments, new com.sun.star.beans.PropertyValue(
877                 "OutputStream", -1, aStream, com.sun.star.beans.PropertyState.DIRECT_VALUE ) );
878 
879         // call normal store method
880         storeToURL( "private:stream", aExtendedArguments );
881 
882         // get byte array from document stream
883         try { aStream.closeOutput(); }
884         catch ( com.sun.star.io.NotConnectedException aExc )
885         { /* TDB */ }
886         catch ( com.sun.star.io.BufferSizeExceededException aExc )
887         { /* TDB */ }
888         catch ( com.sun.star.io.IOException aExc )
889         { throw new java.io.IOException(); }
890         return aOutStream;
891     }
892 
893     /** Stores a document to a byte array.
894 
895         See {@link #storeToURL storeToURL} for further information.
896         @see #storeToURL storeToURL
897      */
storeToByteArray( byte aOutBuffer[], final com.sun.star.beans.PropertyValue aArguments[] )898     public byte[] storeToByteArray(
899             byte aOutBuffer[],
900             final com.sun.star.beans.PropertyValue aArguments[] )
901         throws
902             // @requirement FUNC.CON.LOST/0.2
903             NoConnectionException,
904             NoDocumentException,
905             java.io.IOException,
906             com.sun.star.lang.IllegalArgumentException
907     {
908         // wrap byte array into UNO stream
909         com.sun.star.lib.uno.adapter.XOutputStreamToByteArrayAdapter aStream =
910                 new com.sun.star.lib.uno.adapter.XOutputStreamToByteArrayAdapter(
911                     aOutBuffer );
912 
913         // add stream to arguments
914         com.sun.star.beans.PropertyValue[] aExtendedArguments =
915             addArgument( aArguments, new com.sun.star.beans.PropertyValue(
916                 "OutputStream", -1, aStream, com.sun.star.beans.PropertyState.DIRECT_VALUE ) );
917 
918         // call normal store method
919         storeToURL( "private:stream", aExtendedArguments );
920 
921         // get byte array from document stream
922         try { aStream.closeOutput(); }
923         catch ( com.sun.star.io.NotConnectedException aExc )
924         { /* TDB */ }
925         catch ( com.sun.star.io.BufferSizeExceededException aExc )
926         { /* TDB */ }
927         catch ( com.sun.star.io.IOException aExc )
928         { throw new java.io.IOException(); }
929         return aStream.getBuffer();
930     }
931 
932     // @requirement FUNC.BEAN.PROG/0.5
933     // @requirement API.SIM.SEAP/0.2
934     /** returns the <type scope="com::sun::star::frame">Frame</a>
935         of the bean.
936 
937         @returns
938             a Java class which implements all interfaces which the service
939         <type scope="com::sun::star::frame">Frame</a> implements.
940         Thus, methods can be called directly without queryInterface.
941         This feature might be implemented by UNO or explicitly coded.
942 
943         @throws NoConnectionException
944             if the connection is not established.
945 
946         @throws NotDocumentException
947             if no document is loaded an thus no frame is available.
948      */
getFrame()949     public Frame getFrame()
950 
951         throws
952             NoConnectionException // @requirement FUNC.CON.LOST/0.2
953     {
954         if ( iConnection == null )
955             throw new NoConnectionException();
956         return aFrame;
957     }
958 
959     // @requirement FUNC.BEAN.PROG/0.5
960     // @requirement API.SIM.SEAP/0.2
961     /** returns the <type scope="com::sun::star::frame::Controller"> of the bean.
962 
963         @returns
964             a Java class which implements all interfaces which the service
965         <type scope="com::sun::star::frame">Controller</a> implements.
966         Thus, methods can be called directly without queryInterface.
967         This feature might be implemented by UNO or explicitly coded.
968 
969         @throws NoConnectionException
970             if the connection is not established.
971      */
getController()972     public Controller getController()
973 
974         // @requirement FUNC.CON.LOST/0.2
975         throws NoConnectionException
976     {
977         if ( iConnection == null )
978             throw new NoConnectionException();
979         if ( aController == null )
980             aController = new Controller( aFrame.getController() );
981         return aController;
982     }
983 
984     // @requirement FUNC.BEAN.PROG/0.5
985     // @requirement FUNC.BEAN.STOR/0.4
986     // @requirement FUNC.BEAN.PRNT/0.4
987     // @requirement API.SIM.SEAP/0.2
988     /** returns the <type scope="com::sun::star::document::OfficeDocument">
989         of the bean.
990 
991         @returns
992             a Java class which implements all interfaces which the service
993         <type scope="com::sun::star::document">OfficeDocument</a>
994         implements.
995         Thus, methods can be called directly without queryInterface.
996         This feature might be implemented by UNO or explicitly coded.
997 
998         @throws NoConnectionException
999             if the connection is not established.
1000      */
getDocument()1001     public OfficeDocument getDocument()
1002 
1003         // @requirement FUNC.CON.LOST/0.2
1004         throws NoConnectionException
1005     {
1006         if ( iConnection == null )
1007             throw new NoConnectionException();
1008         return aDocument;
1009     }
1010 
1011     /** Sets visibility of all tool bars known by this OOoBean version.
1012 
1013         Initially all tool bars are visible. By hiding all tool bars
1014         utilizing this method, it is possible to turn just a subset of
1015         tool bars on afterwards, no matter whether all available tool
1016         bars are known or not.
1017         <p>
1018         If an older OOoBean instance is used with a newer AOO instance,
1019         some tool bars might not be affected by this method.
1020         <p>
1021         If no connection is established or no document is loaded,
1022         the setting is memorized until a document is loaded. Same
1023         is valid when the connection dies within this function call.
1024 
1025         @deprecated Clients should use the service com.sun.star.frame.LayoutManager,
1026         which can be obtained from a frame, to control toolbars. For example:
1027         <pre>
1028 com.sun.star.beans.XPropertySet xPropSet =
1029   (com.sun.star.beans.XPropertySet) UnoRuntime.queryInterface(
1030     com.sun.star.beans.XPropertySet.class, aFrame );
1031 com.sun.star.frame.XLayoutManager xLayoutManager =
1032   (com.sun.star.frame.XLayoutManager) UnoRuntime.queryInterface(
1033     com.sun.star.frame.XLayoutManager.class,
1034     xPropSet.getPropertyValue( "LayoutManager" ) );
1035 xLayoutManager.showElement("private:resource/menubar/menubar");
1036         </pre>
1037      */
setAllBarsVisible( boolean bVisible )1038     public void setAllBarsVisible( boolean bVisible )
1039     {
1040         bIgnoreVisibility = true;
1041         setMenuBarVisible( bVisible );
1042         setStandardBarVisible( bVisible );
1043         setToolBarVisible( bVisible );
1044         setStatusBarVisible( bVisible );
1045         bIgnoreVisibility = false;
1046     }
1047 
1048     //--------------------------------------------------------------------------
1049     /** Applies all tool visibilities to the real thing.
1050 
1051         @deprecated Clients should use the service com.sun.star.frame.LayoutManager,
1052         which can be obtained from a frame, to control toolbars. See also
1053         {@link #setAllBarsVisible setAllBarsVisible}.
1054      */
applyToolVisibilities()1055     protected void applyToolVisibilities()
1056         throws
1057             java.lang.InterruptedException
1058     {
1059         bIgnoreVisibility = true;
1060         setMenuBarVisible( bMenuBarVisible );
1061         setStandardBarVisible( bStandardBarVisible );
1062         setToolBarVisible( bToolBarVisible );
1063         setStatusBarVisible( bStatusBarVisible );
1064         bIgnoreVisibility = false;
1065     }
1066 
1067     /** Helper method to set tool bar visibility.
1068 
1069         @param bnewValue
1070             If false, the tool bar is disabled,
1071             If true, the tool bar is visible.
1072 
1073         @deprecated Clients should use the service com.sun.star.frame.LayoutManager,
1074         which can be obtained from a frame, to control toolbars. See also
1075         {@link #setAllBarsVisible}.
1076      */
setToolVisible( String aProperty, String aResourceURL, boolean bOldValue, boolean bNewValue )1077     protected boolean setToolVisible( String aProperty, String aResourceURL,
1078         boolean bOldValue, boolean bNewValue )
1079 
1080         throws
1081             java.lang.InterruptedException
1082     {
1083         // start runtime timeout
1084         CallWatchThread aCallWatchThread =
1085             new CallWatchThread( nOOoCallTimeOut, "setToolVisible" );
1086 
1087         // Does a frame exist?
1088         if ( aFrame != null )
1089         {
1090             if ( bIgnoreVisibility || bOldValue != bNewValue )
1091             {
1092                 try
1093                 {
1094                     com.sun.star.beans.XPropertySet xPropSet =
1095                             (com.sun.star.beans.XPropertySet) UnoRuntime.queryInterface(
1096                             com.sun.star.beans.XPropertySet.class, aFrame );
1097                     com.sun.star.frame.XLayoutManager xLayoutManager =
1098                             (com.sun.star.frame.XLayoutManager) UnoRuntime.queryInterface(
1099                             com.sun.star.frame.XLayoutManager.class,
1100                             xPropSet.getPropertyValue( "LayoutManager" ) );
1101                     if ( bNewValue )
1102                         xLayoutManager.showElement( aResourceURL );
1103                     else
1104                         xLayoutManager.hideElement( aResourceURL );
1105                 }
1106                 catch ( com.sun.star.beans.UnknownPropertyException aExc )
1107                 {
1108                     throw new RuntimeException( "not layout manager found" );
1109                 }
1110                 catch ( com.sun.star.lang.WrappedTargetException aExc )
1111                 {
1112                     throw new RuntimeException( "not layout manager found" );
1113                 }
1114 
1115                 // notify change
1116                 firePropertyChange( aProperty, bOldValue, bNewValue );
1117             }
1118         }
1119 
1120         // end runtime timeout
1121         aCallWatchThread.cancel();
1122 
1123         // the new value will be stored by caller
1124         return bNewValue;
1125     }
1126 
1127     /** Sets the visibility of the menu bar.
1128 
1129         Initially the menu bar is visible.
1130         <p>
1131         If not connected or no document loaded, the value is stored
1132         and automatically applied to the document after it is loaded.
1133         Same is valid when the connection dies within this function call.
1134 
1135         @param bVisible
1136             If false, the menu bar is disabled,
1137             If true, the menu bar is visible.
1138 
1139         @deprecated Clients should use the service com.sun.star.frame.LayoutManager,
1140         which can be obtained from a frame, to control toolbars. See also
1141         {@link #setAllBarsVisible}.
1142      */
setMenuBarVisible(boolean bVisible)1143     public void setMenuBarVisible(boolean bVisible)
1144     {
1145         try
1146         {
1147             bMenuBarVisible = setToolVisible( "MenuBarVisible",
1148                     "private:resource/menubar/menubar", bMenuBarVisible, bVisible );
1149         }
1150         catch ( java.lang.InterruptedException aExc )
1151         {
1152             bMenuBarVisible = bVisible;
1153         }
1154     }
1155 
1156     /** Returns the visibility of the menu bar.
1157 
1158         This method works independently from a connection or loaded document.
1159         If no connection is established or no document is loaded,
1160         this method just returns a memorized status.
1161 
1162         @return
1163             True if the menu bar is visible,
1164             false if the menu bar is hidden.
1165 
1166         @deprecated Clients should use the service com.sun.star.frame.LayoutManager,
1167         which can be obtained from a frame, to control toolbars. See also
1168         {@link #setAllBarsVisible}.
1169      */
isMenuBarVisible()1170     public boolean isMenuBarVisible()
1171     {
1172         return bMenuBarVisible;
1173     }
1174 
1175     /** Sets the main function bar visibility.
1176 
1177         Initially the standard bar is visible.
1178 
1179         If not connected or no document loaded, the value is stored
1180         and automatically applied to the document after it is loaded.
1181         Same is valid when the connection dies within this function call.
1182 
1183         @param bVisible
1184             If false, the main function bar is disabled,
1185             If true, the main function bar is visible.
1186 
1187         @deprecated Clients should use the service com.sun.star.frame.LayoutManager,
1188         which can be obtained from a frame, to control toolbars. See also
1189         {@link #setAllBarsVisible}.
1190      */
setStandardBarVisible(boolean bVisible)1191     public void setStandardBarVisible(boolean bVisible)
1192     {
1193         try
1194         {
1195             bStandardBarVisible = setToolVisible( "StandardBarVisible",
1196                     "private:resource/toolbar/standardbar", bStandardBarVisible, bVisible );
1197         }
1198         catch ( java.lang.InterruptedException aExc )
1199         {
1200             bMenuBarVisible = bVisible;
1201         }
1202     }
1203 
1204     /** Returns the visibility of the main function bar.
1205 
1206         This method works independently from a connection or loaded document.
1207         If no connection is established or no document is loaded,
1208         this method just returns a memorized status.
1209 
1210         @return
1211             True if the main function bar is visible,
1212             false if the main function bar is hidden.
1213 
1214         @deprecated Clients should use the service com.sun.star.frame.LayoutManager,
1215         which can be obtained from a frame, to control toolbars. See also
1216         {@link #setAllBarsVisible}.
1217     */
isStandardBarVisible()1218     public boolean isStandardBarVisible()
1219     {
1220         return bStandardBarVisible;
1221     }
1222 
1223     /** Sets the tool function bar visibility.
1224 
1225         Initially the tool bar is visible.
1226 
1227         If not connected or no document loaded, the value is stored
1228         and automatically applied to the document after it is loaded.
1229         Same is valid when the connection dies within this function call.
1230 
1231         @param bVisible
1232             If false, the tool function bar is disabled,
1233             If true, the tool function bar is visible.
1234 
1235         @deprecated Clients should use the service com.sun.star.frame.LayoutManager,
1236         which can be obtained from a frame, to control toolbars. See also
1237         {@link #setAllBarsVisible}.
1238      */
setToolBarVisible(boolean bVisible)1239     public void setToolBarVisible(boolean bVisible)
1240     {
1241         try
1242         {
1243             bToolBarVisible = setToolVisible( "ToolBarVisible",
1244                     "private:resource/toolbar/toolbar", bToolBarVisible, bVisible );
1245         }
1246         catch ( java.lang.InterruptedException aExc )
1247         {
1248             bMenuBarVisible = bVisible;
1249         }
1250     }
1251 
1252     /** Returns the visibility of the tool function bar.
1253 
1254         This method works independently from a connection or loaded document.
1255         If no connection is established or no document is loaded,
1256         this method just returns a memorized status.
1257 
1258         @return
1259             True if the tool function bar is visible,
1260             false if the tool function bar is hidden.
1261 
1262         @deprecated Clients should use the service com.sun.star.frame.LayoutManager,
1263         which can be obtained from a frame, to control toolbars. See also
1264         {@link #setAllBarsVisible}.
1265      */
isToolBarVisible()1266     public boolean isToolBarVisible()
1267     {
1268         return bToolBarVisible;
1269     }
1270 
1271     /** Sets the status function bar visibility.
1272 
1273         Initially the status bar is visible.
1274 
1275         If not connected or no document loaded, the value is stored
1276         and automatically applied to the document after it is loaded.
1277         Same is valid when the connection dies within this function call.
1278 
1279         @param bVisible
1280             If false, the status function bar is disabled,
1281             If true, the status function bar is visible.
1282 
1283         @deprecated Clients should use the service com.sun.star.frame.LayoutManager,
1284         which can be obtained from a frame, to control toolbars. See also
1285         {@link #setAllBarsVisible}.
1286      */
setStatusBarVisible(boolean bVisible)1287     public void setStatusBarVisible(boolean bVisible)
1288     {
1289         try
1290         {
1291             bStatusBarVisible = setToolVisible( "StatusBarVisible",
1292                     "private:resource/statusbar/statusbar", bStatusBarVisible, bVisible );
1293         }
1294         catch ( java.lang.InterruptedException aExc )
1295         {
1296             bMenuBarVisible = bVisible;
1297         }
1298     }
1299 
1300     /** Returns the visibility of the status function bar.
1301 
1302         This method works independently from a connection or loaded document.
1303         If no connection is established or no document is loaded,
1304         this method just returns a memorized status.
1305 
1306         @return
1307             True if the status function bar is visible,
1308             false if the status function bar is hidden.
1309 
1310         @deprecated Clients should use the service com.sun.star.frame.LayoutManager,
1311         which can be obtained from a frame, to control toolbars. See also
1312         {@link #setAllBarsVisible}.
1313      */
isStatusBarVisible()1314     public boolean isStatusBarVisible()
1315     {
1316         return bStatusBarVisible;
1317     }
1318 
1319     //===========================================================================
1320     // Helper Methods / Internal Methods
1321     //---------------------------------------------------------------------------
1322 
1323     // general instance initializer
1324     {
setLayout(new java.awt.BorderLayout())1325         setLayout(new java.awt.BorderLayout());
1326     }
1327 
1328     /**
1329         @deprecated
1330      */
paint( java.awt.Graphics aGraphics )1331     public void paint( java.awt.Graphics aGraphics )
1332     {
1333     }
1334 
1335     /** Adds a single argument to an array of arguments.
1336 
1337         If the argument by its name is already in aArguments
1338         it is exchanged and aArguments is returned.
1339         <p>
1340         If the argument by its name is not yet in aArguments,
1341         a new array is created, aArgument added and the new
1342         array returned.
1343     */
addArgument( com.sun.star.beans.PropertyValue aArguments[], final com.sun.star.beans.PropertyValue aArgument )1344     protected com.sun.star.beans.PropertyValue[] addArgument(
1345                 com.sun.star.beans.PropertyValue aArguments[],
1346                 final com.sun.star.beans.PropertyValue aArgument )
1347     {
1348         // get number of current arguments
1349         int nNumArgs = 0;
1350         if ( aArguments != null )
1351             nNumArgs = aArguments.length;
1352 
1353         // is new argument already set?
1354         for ( int n = 0; n < nNumArgs; ++n )
1355         {
1356             if ( aArguments[n].Name == aArgument.Name )
1357             {
1358                 // substitute this argument
1359                 aArguments[n] = aArgument;
1360 
1361                 // return current array
1362                 return aArguments;
1363             }
1364         }
1365 
1366         // create extended arguments
1367         com.sun.star.beans.PropertyValue[] aExtendedArguments =
1368             new com.sun.star.beans.PropertyValue[ nNumArgs + 1 ];
1369 
1370         // copy current arguments
1371         for ( int n = 0; n < nNumArgs; ++n )
1372             aExtendedArguments[n] = aArguments[n];
1373 
1374         // add new argument
1375         aExtendedArguments[ nNumArgs ] = aArgument;
1376 
1377         // return new arguments
1378         return aExtendedArguments;
1379     }
1380 
1381     //===========================================================================
1382     // Helper Classes
1383     //---------------------------------------------------------------------------
1384 
1385     /** Helper class to listen on the connection to learn when it dies.
1386 
1387         @internal
1388      */
1389     private class EventListener
1390         extends Thread
1391         implements
1392             com.sun.star.lang.XEventListener,
1393             com.sun.star.frame.XTerminateListener
1394     {
1395         String aTag;
1396 
EventListener( String aTag )1397         EventListener( String aTag )
1398             throws NoConnectionException
1399         {
1400             // init members
1401             this.aTag = aTag;
1402 
1403             // listen on a dying connection
1404             iConnection.addEventListener( this );
1405 
1406             // listen on a terminating AOO
1407             getOOoDesktop().addTerminateListener( this );
1408 
1409             // start this thread as a daemon
1410             setDaemon( true );
1411             start();
1412         }
1413 
end()1414         public void end()
1415         {
1416             // do not listen on a dying connection anymore
1417             try {
1418                 iConnection.removeEventListener( this );
1419             }
1420             catch ( Throwable aExc ) {};
1421 
1422             // do not listen on a terminating AOO anymore
1423             try {
1424                 getOOoDesktop().removeTerminateListener( this );
1425             }
1426             catch ( Throwable aExc ) {};
1427 
1428             // stop thread
1429             this.interrupt();
1430         }
1431 
1432         // gets called when the connection dies
disposing( com.sun.star.lang.EventObject Source )1433         public void disposing( /*IN*/ com.sun.star.lang.EventObject Source )
1434         {
1435             // empty the OOoBean and cut the connection
1436             stopOOoConnection();
1437         }
1438 
1439         // gets called when the user wants to terminate AOO
queryTermination( com.sun.star.lang.EventObject Event )1440         public void queryTermination( /*IN*/ com.sun.star.lang.EventObject Event )
1441             throws com.sun.star.frame.TerminationVetoException
1442         {
1443             // disallow termination of AOO while a OOoBean exists
1444             throw new com.sun.star.frame.TerminationVetoException();
1445         }
1446 
1447         // gets called when AOO terminates
notifyTermination( com.sun.star.lang.EventObject Event )1448         public void notifyTermination( /*IN*/ com.sun.star.lang.EventObject Event )
1449         {
1450             // empty the OOoBean and cut the connection
1451             stopOOoConnection();
1452         }
1453 
1454         // watching the connection
run()1455         public void run()
1456         {
1457             dbgPrint( "EventListener(" + aTag + ").run()" );
1458 
1459             // remote call might hang => watch try
1460             CallWatchThread aCallWatchThread =
1461                 new CallWatchThread( nOOoCallTimeOut, "EventListener(" + aTag + ")" );
1462 
1463             // continue to trying to connect the AOO instance
1464             long n = 0;
1465             while ( isInterrupted() == false
1466                     && iConnection != null
1467                     && iConnection.getComponentContext() != null )
1468             {
1469                 dbgPrint( "EventListener(" + aTag + ").running() #" + ++n );
1470 
1471                 // still alive?
1472                 com.sun.star.lang.XMultiComponentFactory xServiceManager = null;
1473                 try
1474                 {
1475                     // an arbitrary (but cheap) call into AOO
1476                     xServiceManager = iConnection.getComponentContext().getServiceManager();
1477 
1478                     // call successfully performed, restart watch for next loop
1479                     try
1480                     {
1481                         aCallWatchThread.restart();
1482                     }
1483                     catch ( java.lang.InterruptedException aExc )
1484                     {
1485                         // ignore late interrupt
1486                     }
1487                 }
1488                 catch ( java.lang.RuntimeException aExc )
1489                 {
1490                     // hung
1491                     OfficeConnection iDeadConn = iConnection;
1492                     iConnection = null;
1493                     iDeadConn.dispose();
1494                 }
1495 
1496                 // sleep
1497                 try {
1498                         sleep(nOOoCheckCycle);
1499                 }
1500                 catch ( java.lang.InterruptedException aExc )
1501                 {
1502                     dbgPrint("EventListener(" + aTag + ") interupted.");
1503                     // thread can be ended by EventListener.end();
1504                     break;
1505                 }
1506             }
1507         }
1508     }
1509 }
1510