1 /************************************************************************* 2 * 3 * The Contents of this file are made available subject to the terms of 4 * the BSD license. 5 * 6 * Copyright 2000, 2010 Oracle and/or its affiliates. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of Sun Microsystems, Inc. nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 28 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 29 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 30 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 31 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * 33 *************************************************************************/ 34 35 // __________ Imports __________ 36 37 import com.sun.star.uno.UnoRuntime; 38 import com.sun.star.uno.AnyConverter; 39 40 import java.lang.*; 41 import java.awt.*; 42 import javax.swing.*; 43 import java.io.*; 44 import java.net.*; 45 46 // __________ Implementation __________ 47 48 /** 49 * Is a collection of basic features. 50 * This helper shows different functionality of framework api 51 * in an example manner. You can use the follow ones: 52 * (1) parse URL's 53 * (2) create frames (inside/outside a java application) 54 * (3) dispatches (with[out] notifications) 55 * (4) loading/saving documents 56 * (5) convert documents to HTML (if possible) 57 * (6) close documents (and her frames) correctly 58 * 59 * There exist some other helper functionality too, which 60 * doesn't use or demonstrate the office api: 61 * (a) getting file names by using a file chosser 62 * 63 * @author Andreas Schlüns 64 * @created 28.02.2002 15:31 65 */ 66 public class FunctionHelper 67 { 68 // ____________________ 69 70 /** 71 * This convert an URL (formated as a string) to a struct com.sun.star.util.URL. 72 * It use a special service to do that: the URLTransformer. 73 * Because some API calls need it and it's not allowed to set "Complete" 74 * part of the util struct only. The URL must be parsed. 75 * 76 * @param sURL 77 * URL for parsing in string notation 78 * 79 * @return [com.sun.star.util.URL] 80 * URL in UNO struct notation 81 */ 82 public static com.sun.star.util.URL parseURL(String sURL) 83 { 84 com.sun.star.util.URL aURL = null; 85 86 if (sURL==null || sURL.equals("")) 87 { 88 System.out.println("wrong using of URL parser"); 89 return null; 90 } 91 92 try 93 { 94 com.sun.star.uno.XComponentContext xOfficeCtx = 95 OfficeConnect.getOfficeContext(); 96 97 // Create special service for parsing of given URL. 98 com.sun.star.util.XURLTransformer xParser = 99 (com.sun.star.util.XURLTransformer)UnoRuntime.queryInterface( 100 com.sun.star.util.XURLTransformer.class, 101 xOfficeCtx.getServiceManager().createInstanceWithContext( 102 "com.sun.star.util.URLTransformer", xOfficeCtx)); 103 104 // Because it's an in/out parameter we must use an array of URL objects. 105 com.sun.star.util.URL[] aParseURL = new com.sun.star.util.URL[1]; 106 aParseURL[0] = new com.sun.star.util.URL(); 107 aParseURL[0].Complete = sURL; 108 109 // Parse the URL 110 xParser.parseStrict(aParseURL); 111 112 aURL = aParseURL[0]; 113 } 114 catch(com.sun.star.uno.RuntimeException exRuntime) 115 { 116 // Any UNO method of this scope can throw this exception. 117 // Reset the return value only. 118 aURL = null; 119 } 120 catch(com.sun.star.uno.Exception exUno) 121 { 122 // "createInstance()" method of used service manager can throw it. 123 // Then it wasn't possible to get the URL transformer. 124 // Return default instead of realy parsed URL. 125 aURL = null; 126 } 127 128 return aURL; 129 } 130 131 // ____________________ 132 133 /** 134 * create a new empty target frame 135 * Attention: Currently we must use special service com.sun.star.frame.Task instead of Frame. 136 * Because desktop environment accept this special frame type only as direct children. 137 * Note - This service will be deprecated and must be replaces by com.sun.star.frame.Frame in 138 * further versions. To feature prove we use both service names. If for new versions 139 * the deprecated one not exist we get an empty frame, we can try to use the new service. 140 * 141 * @param xSMGR 142 * we nee the remote service manager to create this task/frame service 143 * 144 * @return [com.sun.star.frame.XFrame] 145 * the new created frame reference in case of success or null otherwhise 146 */ 147 private static com.sun.star.frame.XFrame impl_createEmptyFrame( 148 com.sun.star.uno.XComponentContext xCtx ) 149 { 150 com.sun.star.frame.XFrame xFrame = null; 151 152 try{ 153 xFrame = (com.sun.star.frame.XFrame)UnoRuntime.queryInterface( 154 com.sun.star.frame.XFrame.class, 155 xCtx.getServiceManager().createInstanceWithContext( 156 "com.sun.star.frame.Task", xCtx)); 157 } catch(com.sun.star.uno.Exception ex1) {} 158 159 if (xFrame==null) 160 { 161 try{ 162 xFrame = (com.sun.star.frame.XFrame)UnoRuntime.queryInterface( 163 com.sun.star.frame.XFrame.class, 164 xCtx.getServiceManager().createInstanceWithContext( 165 "com.sun.star.frame.Frame", xCtx)); 166 } catch(com.sun.star.uno.Exception ex2) {} 167 } 168 169 return xFrame; 170 } 171 172 // ____________________ 173 174 /** 175 * create a new window which can be used as container window of an office frame 176 * We know two modes for creation: 177 * - the office window will be a child of one of our java windows 178 * - the office will be a normal system window outside this java application 179 * This behaviour will be regulated by the second parameter of this operation. 180 * If a parentview is given the first mode will be activated - otherwhise 181 * the second one. 182 * 183 * Note: First mode (creation of a child window) can be reached by two different 184 * ways. 185 * - pack the required window handle of our java window inside an UNO object 186 * to transport it to the remote office toolkit and get a child office 187 * window. 188 * This is the old way. It's better to use the second one - but to be 189 * future prove this old one should be tried too. 190 * - it's possible to pass the native window handle directly to the toolkit. 191 * A special interface method was enabled to accept that. 192 * 193 * The right way to create an office window should be then: 194 * - try to use second creation mode (directly using of the window handle) 195 * - if it failed ... use the old way by packing the handle inside an object 196 * 197 * @param xSMGR 198 * we need a service manager to be able to create remote office 199 * services 200 * 201 * @param aParentView 202 * the java window as parent for the office window if an inplace office 203 * is required. If it is set to null the created office window will be 204 * a normal system window outside of our java application. 205 * 206 * @return [com.sun.star.awt.XWindow] 207 * The new created office window which can be used to set it as 208 * a ContainerWindow on an empty office frame. 209 */ 210 private static com.sun.star.awt.XWindow impl_createWindow( 211 com.sun.star.uno.XComponentContext xCtx, NativeView aParentView ) 212 { 213 com.sun.star.awt.XWindow xWindow = null; 214 com.sun.star.awt.XWindowPeer xPeer = null; 215 com.sun.star.awt.XToolkit xToolkit = null; 216 217 // get access to toolkit of remote office to create the container window of 218 // new target frame 219 try{ 220 xToolkit = (com.sun.star.awt.XToolkit)UnoRuntime.queryInterface( 221 com.sun.star.awt.XToolkit.class, 222 xCtx.getServiceManager().createInstanceWithContext( 223 "com.sun.star.awt.Toolkit", xCtx)); 224 } 225 catch(com.sun.star.uno.Exception ex) 226 { 227 return null; 228 } 229 230 // mode 1) create an external system window 231 if (aParentView==null) 232 { 233 // Describe the properties of the container window. 234 com.sun.star.awt.WindowDescriptor aDescriptor = 235 new com.sun.star.awt.WindowDescriptor(); 236 aDescriptor.Type = com.sun.star.awt.WindowClass.TOP; 237 aDescriptor.WindowServiceName = "window"; 238 aDescriptor.ParentIndex = -1; 239 aDescriptor.Parent = null; 240 aDescriptor.Bounds = new com.sun.star.awt.Rectangle(0,0,0,0); 241 aDescriptor.WindowAttributes = com.sun.star.awt.WindowAttribute.BORDER | 242 com.sun.star.awt.WindowAttribute.MOVEABLE | 243 com.sun.star.awt.WindowAttribute.SIZEABLE | 244 com.sun.star.awt.WindowAttribute.CLOSEABLE; 245 246 try{ 247 xPeer = xToolkit.createWindow( aDescriptor ); 248 } catch(com.sun.star.lang.IllegalArgumentException exIllegal) {} 249 } 250 // mode 2) create an internal office window as child of our given java 251 // parent window 252 else 253 { 254 // try new version of creation first: directly using of the window 255 // handle. The old implementation of the corresponding toolkit method 256 // requires a process ID. If this id isn't the right one a null object 257 // is returned. But normaly nobody outside the office knows this id. 258 // New version of this method ignore the id parameter and creation will 259 // work. 260 // Note: You must be shure if your window handle can be realy used by 261 // the remote office. Means if this java client and the remote office 262 // use the same display! 263 com.sun.star.awt.XSystemChildFactory xChildFactory = 264 (com.sun.star.awt.XSystemChildFactory)UnoRuntime.queryInterface( 265 com.sun.star.awt.XSystemChildFactory.class, xToolkit); 266 267 try 268 { 269 Integer nHandle = aParentView.getHWND(); 270 short nSystem = (short)aParentView.getNativeWindowSystemType(); 271 byte[] lProcID = new byte[0]; 272 273 xPeer = xChildFactory.createSystemChild((Object)nHandle, 274 lProcID, nSystem); 275 276 if (xPeer==null) 277 { 278 // mode 3) OK - new version doesn't work. It requires the 279 // process id which we doesn't have. 280 // So we must use the old way to get the right window peer. 281 // Pack the handle inside a wrapper object. 282 JavaWindowPeerFake aWrapper = new 283 JavaWindowPeerFake(aParentView); 284 285 com.sun.star.awt.XWindowPeer xParentPeer = 286 (com.sun.star.awt.XWindowPeer)UnoRuntime.queryInterface( 287 com.sun.star.awt.XWindowPeer.class, aWrapper); 288 289 com.sun.star.awt.WindowDescriptor aDescriptor = 290 new com.sun.star.awt.WindowDescriptor(); 291 aDescriptor.Type = com.sun.star.awt.WindowClass.TOP; 292 aDescriptor.WindowServiceName = "workwindow"; 293 aDescriptor.ParentIndex = 1; 294 aDescriptor.Parent = xParentPeer; 295 aDescriptor.Bounds = new com.sun.star.awt.Rectangle(0,0,0,0); 296 if (nSystem == com.sun.star.lang.SystemDependent.SYSTEM_WIN32) 297 aDescriptor.WindowAttributes = 298 com.sun.star.awt.WindowAttribute.SHOW; 299 else 300 aDescriptor.WindowAttributes = 301 com.sun.star.awt.WindowAttribute.SYSTEMDEPENDENT; 302 303 try{ 304 xPeer = xToolkit.createWindow( aDescriptor ); 305 } catch(com.sun.star.lang.IllegalArgumentException exIllegal) {} 306 } 307 } 308 catch(java.lang.RuntimeException exJRun) 309 { 310 // This exception is thrown by the native JNI code if it try to get 311 // the systemw window handle. A possible reason can be an invisible 312 // java window. In this case it should be enough to set return 313 // values to null. All other ressources (which was created before) 314 // will be freed automaticly if scope wil be leaved. 315 System.out.println("May be the NativeView object wasn't realy visible at calling time of getNativeWindow()?"); 316 xPeer = null; 317 xWindow = null; 318 } 319 } 320 321 // It doesn't matter which way was used to get the window peer. 322 // Cast it to the right return interface and return it. 323 xWindow = (com.sun.star.awt.XWindow)UnoRuntime.queryInterface( 324 com.sun.star.awt.XWindow.class, 325 xPeer); 326 327 return xWindow; 328 } 329 330 // ____________________ 331 332 /** 333 * This method create a new empty child frame on desktop instance of remote office. 334 * It use a special JNI functionality to pass the office XWindow over a java window. 335 * This java window can be inserted into another java window container for complex layouting. 336 * If this parent java window isn't used, a top level system window will be created. 337 * The the resulting office frame isn't plugged into this java application. 338 * 339 * @param sName 340 * name to set it on the new created frame 341 * 342 * @param aParentView 343 * java window which should be used as parent window of new created office frame window 344 * May be set to null. 345 * 346 * @return [com.sun.star.frame.XFrame] 347 * reference to the new created frame for success or null if it failed 348 */ 349 public static com.sun.star.frame.XFrame createViewFrame(String sName, NativeView aParentView) 350 { 351 com.sun.star.frame.XFrame xFrame = null; 352 353 try 354 { 355 com.sun.star.uno.XComponentContext xCtx = 356 OfficeConnect.getOfficeContext(); 357 358 // create an empty office frame first 359 xFrame = impl_createEmptyFrame(xCtx); 360 361 // create an office window then 362 // Depending from the given parameter aParentView it will be a child or a top level 363 // system window. (see impl method for further informations) 364 // But before we call this helper - prepare the possible parent window: show it. 365 // JNI calls to get system window handle of java window can't work without that! 366 if (aParentView!=null) 367 aParentView.setVisible(true); 368 com.sun.star.awt.XWindow xWindow = impl_createWindow(xCtx, aParentView); 369 370 // pass the window the frame as his new container window. 371 // It's neccessary to do it first - before you call anything else there. 372 // Otherwhise the frame throws some exceptions for "uninitialized state". 373 xFrame.initialize( xWindow ); 374 375 // Insert the new frame in desktop hierarchy. 376 // Use XFrames interface to do so. It provides access to the child frame container of that instance. 377 com.sun.star.frame.XFramesSupplier xTreeRoot = (com.sun.star.frame.XFramesSupplier)UnoRuntime.queryInterface( 378 com.sun.star.frame.XFramesSupplier.class, 379 xCtx.getServiceManager().createInstanceWithContext( 380 "com.sun.star.frame.Desktop", xCtx)); 381 com.sun.star.frame.XFrames xChildContainer = xTreeRoot.getFrames(); 382 xChildContainer.append(xFrame); 383 384 // Make some further initializations on frame and window. 385 xWindow.setVisible(true); 386 xFrame.setName(sName); 387 } 388 catch(com.sun.star.uno.RuntimeException exRuntime) 389 { 390 // Any UNO method of this scope can throw this exception. 391 // So the frame can be already created and he must be freed 392 // correctly. May be he was inserted into the desktop tree too ... 393 if(xFrame!=null) 394 { 395 // Try to dispose the frame. He should deregister himself at the desktop object 396 // and free all internal used ressources (e.g. the container window) automaticly. 397 // It's possible to do that here - because frame has no component inside yet. 398 // So nobody can disagree with that. 399 // After the dispose() call forget all references to this frame and let him die. 400 // If a new exception will occure ... no generell solution exist then. 401 // Nobody can guarantee if next call will work or not. 402 com.sun.star.lang.XComponent xComponent = (com.sun.star.lang.XComponent)UnoRuntime.queryInterface( 403 com.sun.star.lang.XComponent.class, 404 xFrame); 405 xComponent.dispose(); 406 xComponent = null; 407 xFrame = null; 408 } 409 } 410 catch(com.sun.star.uno.Exception exUno) 411 { 412 // "createInstance()" method of used service manager can throw it. 413 // If it occured during creation of desktop service the frame already was created. 414 // Free it by decresing his refcount. Changes on the desktop tree couldn't exist. 415 // Without the desktop service that wasn't possible. So no further rollbacks must follow. 416 if(xFrame!=null) 417 { 418 com.sun.star.lang.XComponent xComponent = (com.sun.star.lang.XComponent)UnoRuntime.queryInterface( 419 com.sun.star.lang.XComponent.class, 420 xFrame); 421 xComponent.dispose(); 422 xComponent = null; 423 xFrame = null; 424 } 425 } 426 427 return xFrame; 428 } 429 430 // ____________________ 431 432 /** 433 * Dispatch an URL to given frame. 434 * Caller can register himself for following status events for dispatched 435 * URL too. But nobody guarantee that such notifications will occure. 436 * (see dispatchWithNotification() if you interest on that) 437 * The returned dispatch object should be hold alive by caller 438 * till he deosn't need it any longer. Otherwise the dispatcher can(!) 439 * die by decreasing his refcount. 440 * 441 * @param xFrame frame wich should be the target of this dispatch 442 * @param aURL full parsed and converted office URL for dispatch 443 * @param lProperties optional arguments for dispatch 444 * @param xListener optional listener which is registered automaticly for status events 445 * (Note: Deregistration is part of this listener himself!) 446 * 447 * @return [XDispatch] It's the used dispatch object and can be used for deregistration of an optional listener. 448 * Otherwhise caller can ignore it. 449 */ 450 public static com.sun.star.frame.XDispatch execute(com.sun.star.frame.XFrame xFrame , 451 com.sun.star.util.URL aURL , 452 com.sun.star.beans.PropertyValue[] lProperties, 453 com.sun.star.frame.XStatusListener xListener ) 454 { 455 com.sun.star.frame.XDispatch xDispatcher = null; 456 457 try 458 { 459 // Query the frame for right interface which provides access to all available dispatch objects. 460 com.sun.star.frame.XDispatchProvider xProvider = (com.sun.star.frame.XDispatchProvider)UnoRuntime.queryInterface( 461 com.sun.star.frame.XDispatchProvider.class, 462 xFrame); 463 464 // Ask himn for right dispatch object for given URL. 465 // Force given frame as target for following dispatch by using "". 466 // It means the same like "_self". 467 xDispatcher = xProvider.queryDispatch(aURL,"",0); 468 469 // Dispatch the URL into the frame. 470 if(xDispatcher!=null) 471 { 472 if(xListener!=null) 473 xDispatcher.addStatusListener(xListener,aURL); 474 475 xDispatcher.dispatch(aURL,lProperties); 476 } 477 } 478 catch(com.sun.star.uno.RuntimeException exUno) 479 { 480 // Any UNO method of this scope can throw this exception. 481 // But there will be nothing to do then - because 482 // we haven't changed anything inside the remote objects 483 // except method "addStatusListener(). 484 // But in this case the source of this exception has to 485 // rollback all his operations. There is no chance to 486 // make anything right then. 487 // Reset the return value to a default - that's it. 488 exUno.printStackTrace(); 489 xDispatcher = null; 490 } 491 492 return xDispatcher; 493 } 494 495 // ____________________ 496 497 /** 498 * Dispatch an URL to given frame. 499 * Caller can register himself for following result events for dispatched 500 * URL too. Notifications are guaranteed (instead of dispatch()) 501 * Returning of the dispatch object isn't neccessary. 502 * Nobody must hold it alive longer the dispatch needs. 503 * 504 * @param xFrame frame wich should be the target of this dispatch 505 * @param aURL full parsed and converted office URL for dispatch 506 * @param lProperties optional arguments for dispatch 507 * @param xListener optional listener which is registered automaticly for status events 508 * (Note: Deregistration is not supported. Dispatcher does it automaticly.) 509 */ 510 public static void executeWithNotification(com.sun.star.frame.XFrame xFrame , 511 com.sun.star.util.URL aURL , 512 com.sun.star.beans.PropertyValue[] lProperties, 513 com.sun.star.frame.XDispatchResultListener xListener ) 514 { 515 try 516 { 517 // Query the frame for right interface which provides access to all available dispatch objects. 518 com.sun.star.frame.XDispatchProvider xProvider = (com.sun.star.frame.XDispatchProvider)UnoRuntime.queryInterface( 519 com.sun.star.frame.XDispatchProvider.class, 520 xFrame); 521 522 // Ask himn for right dispatch object for given URL. 523 // Force THIS frame as target for following dispatch. 524 // Attention: The interface XNotifyingDispatch is an optional one! 525 com.sun.star.frame.XDispatch xDispatcher = xProvider.queryDispatch(aURL,"",0); 526 com.sun.star.frame.XNotifyingDispatch xNotifyingDispatcher = (com.sun.star.frame.XNotifyingDispatch)UnoRuntime.queryInterface( 527 com.sun.star.frame.XNotifyingDispatch.class, 528 xDispatcher); 529 530 // Dispatch the URL. 531 if(xNotifyingDispatcher!=null) 532 xNotifyingDispatcher.dispatchWithNotification(aURL,lProperties,xListener); 533 } 534 catch(com.sun.star.uno.RuntimeException exUno) 535 { 536 // Any UNO method of this scope can throw this exception. 537 // But there is nothing we can do then. 538 exUno.printStackTrace(); 539 } 540 } 541 542 // ____________________ 543 544 /** 545 * Load document specified by an URL into given frame synchronously. 546 * The result of this operation will be the loaded document for success 547 * or null if loading failed. 548 * 549 * @param xFrame frame wich should be the target of this load call 550 * @param sURL unparsed URL for loading 551 * @param lProperties optional arguments 552 * 553 * @return [XComponent] the loaded document for success or null if it's failed 554 */ 555 public static com.sun.star.lang.XComponent loadDocument( 556 com.sun.star.frame.XFrame xFrame, String sURL, 557 com.sun.star.beans.PropertyValue[] lProperties) 558 { 559 com.sun.star.lang.XComponent xDocument = null; 560 String sOldName = null; 561 562 try 563 { 564 com.sun.star.uno.XComponentContext xCtx = 565 OfficeConnect.getOfficeContext(); 566 567 // First prepare frame for loading 568 // We must adress it inside the frame tree without any complications. 569 // So we set an unambigous (we hope it) name and use it later. 570 // Don't forget to reset original name after that. 571 sOldName = xFrame.getName(); 572 String sTarget = "odk_officedev_desk"; 573 xFrame.setName(sTarget); 574 575 // Get access to the global component loader of the office 576 // for synchronous loading the document. 577 com.sun.star.frame.XComponentLoader xLoader = 578 (com.sun.star.frame.XComponentLoader)UnoRuntime.queryInterface( 579 com.sun.star.frame.XComponentLoader.class, 580 xCtx.getServiceManager().createInstanceWithContext( 581 "com.sun.star.frame.Desktop", xCtx)); 582 583 // Load the document into the target frame by using his name and 584 // special search flags. 585 xDocument = xLoader.loadComponentFromURL( 586 sURL, 587 sTarget, 588 com.sun.star.frame.FrameSearchFlag.CHILDREN, 589 lProperties); 590 591 // dont forget to restore old frame name ... 592 xFrame.setName(sOldName); 593 } 594 catch(com.sun.star.io.IOException exIO) 595 { 596 // Can be thrown by "loadComponentFromURL()" call. 597 // The only thing we should do then is to reset changed frame name! 598 exIO.printStackTrace(); 599 xDocument = null; 600 if(sOldName!=null) 601 xFrame.setName(sOldName); 602 } 603 catch(com.sun.star.lang.IllegalArgumentException exIllegal) 604 { 605 // Can be thrown by "loadComponentFromURL()" call. 606 // The only thing we should do then is to reset changed frame name! 607 exIllegal.printStackTrace(); 608 xDocument = null; 609 if(sOldName!=null) 610 xFrame.setName(sOldName); 611 } 612 catch(com.sun.star.uno.RuntimeException exRuntime) 613 { 614 // Any UNO method of this scope can throw this exception. 615 // The only thing we can try(!) is to reset changed frame name. 616 exRuntime.printStackTrace(); 617 xDocument = null; 618 if(sOldName!=null) 619 xFrame.setName(sOldName); 620 } 621 catch(com.sun.star.uno.Exception exUno) 622 { 623 // "createInstance()" method of used service manager can throw it. 624 // The only thing we should do then is to reset changed frame name! 625 exUno.printStackTrace(); 626 xDocument = null; 627 if(sOldName!=null) 628 xFrame.setName(sOldName); 629 } 630 631 return xDocument; 632 } 633 634 // ____________________ 635 636 /** 637 * Save currently loaded document of given frame. 638 * 639 * @param xDocument document for saving changes 640 */ 641 public static void saveDocument(com.sun.star.lang.XComponent xDocument) 642 { 643 try 644 { 645 // Check for supported model functionality. 646 // Normaly the application documents (text, spreadsheet ...) do so 647 // but some other ones (e.g. db components) doesn't do that. 648 // They can't be save then. 649 com.sun.star.frame.XModel xModel = (com.sun.star.frame.XModel)UnoRuntime.queryInterface( 650 com.sun.star.frame.XModel.class, 651 xDocument); 652 if(xModel!=null) 653 { 654 // Check for modifications => break save process if there is nothing to do. 655 com.sun.star.util.XModifiable xModified = (com.sun.star.util.XModifiable)UnoRuntime.queryInterface( 656 com.sun.star.util.XModifiable.class, 657 xModel); 658 if(xModified.isModified()==true) 659 { 660 com.sun.star.frame.XStorable xStore = (com.sun.star.frame.XStorable)UnoRuntime.queryInterface( 661 com.sun.star.frame.XStorable.class, 662 xModel); 663 664 xStore.store(); 665 } 666 } 667 } 668 catch(com.sun.star.io.IOException exIO) 669 { 670 // Can be thrown by "store()" call. 671 // But there is nothing we can do then. 672 exIO.printStackTrace(); 673 } 674 catch(com.sun.star.uno.RuntimeException exUno) 675 { 676 // Any UNO method of this scope can throw this exception. 677 // But there is nothing we can do then. 678 exUno.printStackTrace(); 679 } 680 } 681 682 // ____________________ 683 684 /** 685 * It try to export given document in HTML format. 686 * Current document will be converted to HTML and moved to new place on disk. 687 * A "new" file will be created by given URL (may be overwritten 688 * if it already exist). Right filter will be used automaticly if factory of 689 * this document support it. If no valid filter can be found for export, 690 * nothing will be done here. 691 * 692 * @param xDocument document which should be exported 693 * @param sURL target URL for converted document 694 */ 695 public static void saveAsHTML(com.sun.star.lang.XComponent xDocument, 696 String sURL ) 697 { 698 try 699 { 700 // First detect factory of this document. 701 // Ask for the supported service name of this document. 702 // If information is available it can be used to find out wich 703 // filter exist for HTML export. Normaly this filter should be searched 704 // inside the filter configuration but this little demo doesn't do so. 705 // (see service com.sun.star.document.FilterFactory for further 706 // informations too) 707 // Well known filter names are used directly. They must exist in current 708 // office installation. Otherwise this code will fail. But to prevent 709 // this code against missing filters it check for existing state of it. 710 com.sun.star.lang.XServiceInfo xInfo = (com.sun.star.lang.XServiceInfo) 711 UnoRuntime.queryInterface(com.sun.star.lang.XServiceInfo.class, 712 xDocument); 713 714 if(xInfo!=null) 715 { 716 // Find out possible filter name. 717 String sFilter = null; 718 if(xInfo.supportsService("com.sun.star.text.TextDocument")==true) 719 sFilter = new String("HTML (StarWriter)"); 720 else 721 if(xInfo.supportsService("com.sun.star.text.WebDocument")==true) 722 sFilter = new String("HTML"); 723 else 724 if(xInfo.supportsService("com.sun.star.sheet.SpreadsheetDocument")==true) 725 sFilter = new String("HTML (StarCalc)"); 726 727 // Check for existing state of this filter. 728 if(sFilter!=null) 729 { 730 com.sun.star.uno.XComponentContext xCtx = 731 OfficeConnect.getOfficeContext(); 732 733 com.sun.star.container.XNameAccess xFilterContainer = 734 (com.sun.star.container.XNameAccess) 735 UnoRuntime.queryInterface( 736 com.sun.star.container.XNameAccess.class, 737 xCtx.getServiceManager().createInstanceWithContext( 738 "com.sun.star.document.FilterFactory", xCtx)); 739 740 if(xFilterContainer.hasByName(sFilter)==false) 741 sFilter=null; 742 } 743 744 // Use this filter for export. 745 if(sFilter!=null) 746 { 747 // Export can be forced by saving the document and using a 748 // special filter name which can write needed format. Build 749 // neccessary argument list now. 750 // Use special flag "Overwrite" too, to prevent operation 751 // against possible exceptions, if file already exist. 752 com.sun.star.beans.PropertyValue[] lProperties = 753 new com.sun.star.beans.PropertyValue[2]; 754 lProperties[0] = new com.sun.star.beans.PropertyValue(); 755 lProperties[0].Name = "FilterName"; 756 lProperties[0].Value = sFilter; 757 lProperties[1] = new com.sun.star.beans.PropertyValue(); 758 lProperties[1].Name = "Overwrite"; 759 lProperties[1].Value = Boolean.TRUE; 760 761 com.sun.star.frame.XStorable xStore = 762 (com.sun.star.frame.XStorable)UnoRuntime.queryInterface( 763 com.sun.star.frame.XStorable.class, xDocument); 764 765 xStore.storeAsURL(sURL,lProperties); 766 } 767 } 768 } 769 catch(com.sun.star.io.IOException exIO) 770 { 771 // Can be thrown by "store()" call. 772 // Do nothing then. Saving failed - that's it. 773 exIO.printStackTrace(); 774 } 775 catch(com.sun.star.uno.RuntimeException exRuntime) 776 { 777 // Can be thrown by any uno call. 778 // Do nothing here. Saving failed - that's it. 779 exRuntime.printStackTrace(); 780 } 781 catch(com.sun.star.uno.Exception exUno) 782 { 783 // Can be thrown by "createInstance()" call of service manager. 784 // Do nothing here. Saving failed - that's it. 785 exUno.printStackTrace(); 786 } 787 } 788 789 // ____________________ 790 791 /** 792 * Try to close the document without any saving of modifications. 793 * We can try it only! Controller and/or model of this document 794 * can disagree with that. But mostly they doesn't do so. 795 * 796 * @param xDocument document which should be clcosed 797 */ 798 public static void closeDocument(com.sun.star.lang.XComponent xDocument) 799 { 800 try 801 { 802 // Check supported functionality of the document (model or controller). 803 com.sun.star.frame.XModel xModel = 804 (com.sun.star.frame.XModel)UnoRuntime.queryInterface( 805 com.sun.star.frame.XModel.class, xDocument); 806 807 if(xModel!=null) 808 { 809 // It's a full featured office document. 810 // Reset the modify state of it and close it. 811 // Note: Model can disgree by throwing a veto exception. 812 com.sun.star.util.XModifiable xModify = 813 (com.sun.star.util.XModifiable)UnoRuntime.queryInterface( 814 com.sun.star.util.XModifiable.class, xModel); 815 816 xModify.setModified(false); 817 xDocument.dispose(); 818 } 819 else 820 { 821 // It's a document which supports a controller .. or may by a pure 822 // window only. If it's at least a controller - we can try to 823 // suspend him. But - he can disagree with that! 824 com.sun.star.frame.XController xController = 825 (com.sun.star.frame.XController)UnoRuntime.queryInterface( 826 com.sun.star.frame.XController.class, xDocument); 827 828 if(xController!=null) 829 { 830 if(xController.suspend(true)==true) 831 { 832 // Note: Don't dispose the controller - destroy the frame 833 // to make it right! 834 com.sun.star.frame.XFrame xFrame = xController.getFrame(); 835 xFrame.dispose(); 836 } 837 } 838 } 839 } 840 catch(com.sun.star.beans.PropertyVetoException exVeto) 841 { 842 // Can be thrown by "setModified()" call on model. 843 // He disagree with our request. 844 // But there is nothing to do then. Following "dispose()" call wasn't 845 // never called (because we catch it before). Closing failed -that's it. 846 exVeto.printStackTrace(); 847 } 848 catch(com.sun.star.lang.DisposedException exDisposed) 849 { 850 // If an UNO object was already disposed before - he throw this special 851 // runtime exception. Of course every UNO call must be look for that - 852 // but it's a question of error handling. 853 // For demonstration this exception is handled here. 854 exDisposed.printStackTrace(); 855 } 856 catch(com.sun.star.uno.RuntimeException exRuntime) 857 { 858 // Every uno call can throw that. 859 // Do nothing - closing failed - that's it. 860 exRuntime.printStackTrace(); 861 } 862 } 863 864 // ____________________ 865 866 /** 867 * Try to close the frame instead of the document. 868 * It shows the possible interface to do so. 869 * 870 * @param xFrame 871 * frame which should be clcosed 872 * 873 * @return <TRUE/> in case frame could be closed 874 * <FALSE/> otherwise 875 */ 876 public static boolean closeFrame(com.sun.star.frame.XFrame xFrame) 877 { 878 boolean bClosed = false; 879 880 try 881 { 882 // first try the new way: use new interface XCloseable 883 // It replace the deprecated XTask::close() and should be preferred ... 884 // if it can be queried. 885 com.sun.star.util.XCloseable xCloseable = 886 (com.sun.star.util.XCloseable)UnoRuntime.queryInterface( 887 com.sun.star.util.XCloseable.class, xFrame); 888 if (xCloseable!=null) 889 { 890 // We deliver the owner ship of this frame not to the (possible) 891 // source which throw a CloseVetoException. We whishto have it 892 // under our own control. 893 try 894 { 895 xCloseable.close(false); 896 bClosed = true; 897 } 898 catch( com.sun.star.util.CloseVetoException exVeto ) 899 { 900 bClosed = false; 901 } 902 } 903 else 904 { 905 // OK: the new way isn't possible. Try the old one. 906 com.sun.star.frame.XTask xTask = (com.sun.star.frame.XTask) 907 UnoRuntime.queryInterface(com.sun.star.frame.XTask.class, 908 xFrame); 909 if (xTask!=null) 910 { 911 // return value doesn't interest here. Because 912 // we forget this task ... 913 bClosed = xTask.close(); 914 } 915 } 916 } 917 catch (com.sun.star.lang.DisposedException exDisposed) 918 { 919 // Of course - this task can be already dead - means disposed. 920 // But for us it's not important. Because we tried to close it too. 921 // And "already disposed" or "closed" should be the same ... 922 bClosed = true; 923 } 924 925 return bClosed; 926 } 927 928 // ____________________ 929 930 /** 931 * Try to find an unique frame name, which isn't currently used inside 932 * remote office instance. Because we create top level frames 933 * only, it's enough to check the names of existing child frames on the 934 * desktop only. 935 * 936 * @return [String] 937 * should represent an unique frame name, which currently isn't 938 * used inside the remote office frame tree 939 * (Couldn't guaranteed for a real multithreaded environment. 940 * But we try it ...) 941 */ 942 private static final String BASEFRAMENAME = "Desk View "; 943 944 public static String getUniqueFrameName() 945 { 946 String sName = null; 947 948 com.sun.star.uno.XComponentContext xCtx = OfficeConnect.getOfficeContext(); 949 950 try 951 { 952 com.sun.star.frame.XFramesSupplier xSupplier = 953 (com.sun.star.frame.XFramesSupplier)UnoRuntime.queryInterface( 954 com.sun.star.frame.XFramesSupplier.class, 955 xCtx.getServiceManager().createInstanceWithContext( 956 "com.sun.star.frame.Desktop", xCtx)); 957 958 com.sun.star.container.XIndexAccess xContainer = 959 (com.sun.star.container.XIndexAccess)UnoRuntime.queryInterface( 960 com.sun.star.container.XIndexAccess.class, 961 xSupplier.getFrames()); 962 963 int nCount = xContainer.getCount(); 964 for (int i=0; i<nCount; ++i ) 965 { 966 com.sun.star.frame.XFrame xFrame = (com.sun.star.frame.XFrame)AnyConverter.toObject(new com.sun.star.uno.Type(com.sun.star.frame.XFrame.class), xContainer.getByIndex(i)); 967 sName = new String(BASEFRAMENAME+mnViewCount); 968 while(sName.compareTo(xFrame.getName())==0) 969 { 970 ++mnViewCount; 971 sName = new String(BASEFRAMENAME+mnViewCount); 972 } 973 } 974 } 975 catch(com.sun.star.uno.Exception exCreateFailed) 976 { 977 sName = new String(BASEFRAMENAME); 978 } 979 980 if (sName==null) 981 { 982 System.out.println("invalid name!"); 983 sName = new String(BASEFRAMENAME); 984 } 985 986 return sName; 987 } 988 989 // ____________________ 990 991 /** 992 * helper to get a file URL selected by user 993 * This method doesn't show any API concepts ... 994 * but is neccessary rof this demo application. 995 * 996 * @param aParent parent window of this dialog 997 * @param bOpen If it is set to true => 998 * dialog is opend in "file open" mode - 999 * otherwise in "file save" mode. 1000 */ 1001 public static String askUserForFileURL(Component aParent,boolean bOpen) 1002 { 1003 String sFileURL = null; 1004 int nDecision = JFileChooser.CANCEL_OPTION; 1005 JFileChooser aChooser = null; 1006 1007 // set last visited directory on new file chosser 1008 // (if this information is available) 1009 if( maLastDir==null ) 1010 aChooser = new JFileChooser(); 1011 else 1012 aChooser = new JFileChooser(maLastDir); 1013 1014 // decide between file open/save dialog 1015 if( bOpen==true ) 1016 nDecision = aChooser.showOpenDialog(aParent); 1017 else 1018 nDecision = aChooser.showSaveDialog(aParent); 1019 1020 // react for "OK" result only 1021 if(nDecision == JFileChooser.APPROVE_OPTION) 1022 { 1023 // save current directory as last visited one 1024 maLastDir = aChooser.getCurrentDirectory(); 1025 // get file URL from the dialog 1026 try 1027 { 1028 sFileURL = aChooser.getSelectedFile().toURL().toExternalForm(); 1029 } 1030 catch( MalformedURLException ex ) 1031 { 1032 ex.printStackTrace(); 1033 sFileURL = null; 1034 } 1035 // problem of java: file URL's are coded with 1 slash instead of 3 ones! 1036 // => correct this problem first, otherwise office can't use these URL's 1037 if( 1038 ( sFileURL !=null ) && 1039 ( sFileURL.startsWith("file:/") ==true ) && 1040 ( sFileURL.startsWith("file://")==false ) 1041 ) 1042 { 1043 StringBuffer sWorkBuffer = new StringBuffer(sFileURL); 1044 sWorkBuffer.insert(6,"//"); 1045 sFileURL = sWorkBuffer.toString(); 1046 } 1047 } 1048 1049 return sFileURL; 1050 } 1051 1052 // ____________________ 1053 1054 /** 1055 * @member maLastDir save the last visited directory of used file open/save dialog 1056 * @member mnViewCount we try to set unique names on every frame we create (that's why we must count it) 1057 */ 1058 private static File maLastDir = null; 1059 private static int mnViewCount = 0 ; 1060 } 1061