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 
1511