/************************************************************************* * * The Contents of this file are made available subject to the terms of * the BSD license. * * Copyright 2000, 2010 Oracle and/or its affiliates. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *************************************************************************/ // __________ Imports __________ import com.sun.star.uno.UnoRuntime; import com.sun.star.uno.AnyConverter; import java.awt.*; import javax.swing.*; import java.io.*; import java.net.*; // __________ Implementation __________ /** * Is a collection of basic features. * This helper shows different functionality of framework api * in an example manner. You can use the follow ones: * (1) parse URL's * (2) create frames (inside/outside a java application) * (3) dispatches (with[out] notifications) * (4) loading/saving documents * (5) convert documents to HTML (if possible) * (6) close documents (and her frames) correctly * * There exist some other helper functionality too, which * doesn't use or demonstrate the office api: * (a) getting file names by using a file chosser */ public class FunctionHelper { /** * This convert an URL (formated as a string) to a struct com.sun.star.util.URL. * It use a special service to do that: the URLTransformer. * Because some API calls need it and it's not allowed to set "Complete" * part of the util struct only. The URL must be parsed. * * @param sURL * URL for parsing in string notation * * @return [com.sun.star.util.URL] * URL in UNO struct notation */ public static com.sun.star.util.URL parseURL(String sURL) { com.sun.star.util.URL aURL = null; if (sURL==null || sURL.equals("")) { System.out.println("wrong using of URL parser"); return null; } try { com.sun.star.uno.XComponentContext xOfficeCtx = OfficeConnect.getOfficeContext(); // Create special service for parsing of given URL. com.sun.star.util.XURLTransformer xParser = UnoRuntime.queryInterface( com.sun.star.util.XURLTransformer.class, xOfficeCtx.getServiceManager().createInstanceWithContext( "com.sun.star.util.URLTransformer", xOfficeCtx)); // Because it's an in/out parameter we must use an array of URL objects. com.sun.star.util.URL[] aParseURL = new com.sun.star.util.URL[1]; aParseURL[0] = new com.sun.star.util.URL(); aParseURL[0].Complete = sURL; // Parse the URL xParser.parseStrict(aParseURL); aURL = aParseURL[0]; } catch(com.sun.star.uno.RuntimeException exRuntime) { // Any UNO method of this scope can throw this exception. // Reset the return value only. aURL = null; } catch(com.sun.star.uno.Exception exUno) { // "createInstance()" method of used service manager can throw it. // Then it wasn't possible to get the URL transformer. // Return default instead of really parsed URL. aURL = null; } return aURL; } /** * create a new empty target frame * Attention: Currently we must use special service com.sun.star.frame.Task instead of Frame. * Because desktop environment accept this special frame type only as direct children. * Note - This service will be deprecated and must be replaces by com.sun.star.frame.Frame in * further versions. To feature prove we use both service names. If for new versions * the deprecated one not exist we get an empty frame, we can try to use the new service. * * @param xSMGR * we nee the remote service manager to create this task/frame service * * @return [com.sun.star.frame.XFrame] * the new created frame reference in case of success or null otherwise */ private static com.sun.star.frame.XFrame impl_createEmptyFrame( com.sun.star.uno.XComponentContext xCtx ) { com.sun.star.frame.XFrame xFrame = null; try{ xFrame = UnoRuntime.queryInterface( com.sun.star.frame.XFrame.class, xCtx.getServiceManager().createInstanceWithContext( "com.sun.star.frame.Task", xCtx)); } catch(com.sun.star.uno.Exception ex1) {} if (xFrame==null) { try{ xFrame = UnoRuntime.queryInterface( com.sun.star.frame.XFrame.class, xCtx.getServiceManager().createInstanceWithContext( "com.sun.star.frame.Frame", xCtx)); } catch(com.sun.star.uno.Exception ex2) {} } return xFrame; } /** * create a new window which can be used as container window of an office frame * We know two modes for creation: * - the office window will be a child of one of our java windows * - the office will be a normal system window outside this java application * This behaviour will be regulated by the second parameter of this operation. * If a parentview is given the first mode will be activated - otherwise * the second one. * * Note: First mode (creation of a child window) can be reached by two different * ways. * - pack the required window handle of our java window inside an UNO object * to transport it to the remote office toolkit and get a child office * window. * This is the old way. It's better to use the second one - but to be * future prove this old one should be tried too. * - it's possible to pass the native window handle directly to the toolkit. * A special interface method was enabled to accept that. * * The right way to create an office window should be then: * - try to use second creation mode (directly using of the window handle) * - if it failed ... use the old way by packing the handle inside an object * * @param xSMGR * we need a service manager to be able to create remote office * services * * @param aParentView * the java window as parent for the office window if an inplace office * is required. If it is set to null the created office window will be * a normal system window outside of our java application. * * @return [com.sun.star.awt.XWindow] * The new created office window which can be used to set it as * a ContainerWindow on an empty office frame. */ private static com.sun.star.awt.XWindow impl_createWindow( com.sun.star.uno.XComponentContext xCtx, NativeView aParentView ) { com.sun.star.awt.XWindow xWindow = null; com.sun.star.awt.XWindowPeer xPeer = null; com.sun.star.awt.XToolkit xToolkit = null; // get access to toolkit of remote office to create the container window of // new target frame try{ xToolkit = UnoRuntime.queryInterface( com.sun.star.awt.XToolkit.class, xCtx.getServiceManager().createInstanceWithContext( "com.sun.star.awt.Toolkit", xCtx)); } catch(com.sun.star.uno.Exception ex) { return null; } // mode 1) create an external system window if (aParentView==null) { // Describe the properties of the container window. com.sun.star.awt.WindowDescriptor aDescriptor = new com.sun.star.awt.WindowDescriptor(); aDescriptor.Type = com.sun.star.awt.WindowClass.TOP; aDescriptor.WindowServiceName = "window"; aDescriptor.ParentIndex = -1; aDescriptor.Parent = null; aDescriptor.Bounds = new com.sun.star.awt.Rectangle(0,0,0,0); aDescriptor.WindowAttributes = com.sun.star.awt.WindowAttribute.BORDER | com.sun.star.awt.WindowAttribute.MOVEABLE | com.sun.star.awt.WindowAttribute.SIZEABLE | com.sun.star.awt.WindowAttribute.CLOSEABLE; try{ xPeer = xToolkit.createWindow( aDescriptor ); } catch(com.sun.star.lang.IllegalArgumentException exIllegal) {} } // mode 2) create an internal office window as child of our given java // parent window else { // try new version of creation first: directly using of the window // handle. The old implementation of the corresponding toolkit method // requires a process ID. If this id isn't the right one a null object // is returned. But normaly nobody outside the office knows this id. // New version of this method ignore the id parameter and creation will // work. // Note: You must be sure if your window handle can be really used by // the remote office. Means if this java client and the remote office // use the same display! com.sun.star.awt.XSystemChildFactory xChildFactory = UnoRuntime.queryInterface( com.sun.star.awt.XSystemChildFactory.class, xToolkit); try { Integer nHandle = aParentView.getHWND(); short nSystem = (short)aParentView.getNativeWindowSystemType(); byte[] lProcID = new byte[0]; xPeer = xChildFactory.createSystemChild(nHandle, lProcID, nSystem); if (xPeer==null) { // mode 3) OK - new version doesn't work. It requires the // process id which we don't have. // So we must use the old way to get the right window peer. // Pack the handle inside a wrapper object. JavaWindowPeerFake aWrapper = new JavaWindowPeerFake(aParentView); com.sun.star.awt.XWindowPeer xParentPeer = UnoRuntime.queryInterface( com.sun.star.awt.XWindowPeer.class, aWrapper); com.sun.star.awt.WindowDescriptor aDescriptor = new com.sun.star.awt.WindowDescriptor(); aDescriptor.Type = com.sun.star.awt.WindowClass.TOP; aDescriptor.WindowServiceName = "workwindow"; aDescriptor.ParentIndex = 1; aDescriptor.Parent = xParentPeer; aDescriptor.Bounds = new com.sun.star.awt.Rectangle(0,0,0,0); if (nSystem == com.sun.star.lang.SystemDependent.SYSTEM_WIN32) aDescriptor.WindowAttributes = com.sun.star.awt.WindowAttribute.SHOW; else aDescriptor.WindowAttributes = com.sun.star.awt.WindowAttribute.SYSTEMDEPENDENT; try{ xPeer = xToolkit.createWindow( aDescriptor ); } catch(com.sun.star.lang.IllegalArgumentException exIllegal) {} } } catch(java.lang.RuntimeException exJRun) { // This exception is thrown by the native JNI code if it try to get // the systemw window handle. A possible reason can be an invisible // java window. In this case it should be enough to set return // values to null. All other resources (which was created before) // will be freed automatically if scope wil be leaved. System.out.println("May be the NativeView object wasn't really visible at calling time of getNativeWindow()?"); xPeer = null; xWindow = null; } } // It doesn't matter which way was used to get the window peer. // Cast it to the right return interface and return it. xWindow = UnoRuntime.queryInterface( com.sun.star.awt.XWindow.class, xPeer); return xWindow; } /** * This method create a new empty child frame on desktop instance of remote office. * It use a special JNI functionality to pass the office XWindow over a java window. * This java window can be inserted into another java window container for complex layouting. * If this parent java window isn't used, a top level system window will be created. * The resulting office frame isn't plugged into this java application. * * @param sName * name to set it on the new created frame * * @param aParentView * java window which should be used as parent window of new created office frame window * May be set to null. * * @return [com.sun.star.frame.XFrame] * reference to the new created frame for success or null if it failed */ public static com.sun.star.frame.XFrame createViewFrame(String sName, NativeView aParentView) { com.sun.star.frame.XFrame xFrame = null; try { com.sun.star.uno.XComponentContext xCtx = OfficeConnect.getOfficeContext(); // create an empty office frame first xFrame = impl_createEmptyFrame(xCtx); // create an office window then // Depending from the given parameter aParentView it will be a child or a top level // system window. (see impl method for further information) // But before we call this helper - prepare the possible parent window: show it. // JNI calls to get system window handle of java window can't work without that! if (aParentView!=null) aParentView.setVisible(true); com.sun.star.awt.XWindow xWindow = impl_createWindow(xCtx, aParentView); // pass the window the frame as his new container window. // It's necessary to do it first - before you call anything else there. // Otherwhise the frame throws some exceptions for "uninitialized state". xFrame.initialize( xWindow ); // Insert the new frame in desktop hierarchy. // Use XFrames interface to do so. It provides access to the child frame container of that instance. com.sun.star.frame.XFramesSupplier xTreeRoot = UnoRuntime.queryInterface( com.sun.star.frame.XFramesSupplier.class, xCtx.getServiceManager().createInstanceWithContext( "com.sun.star.frame.Desktop", xCtx)); com.sun.star.frame.XFrames xChildContainer = xTreeRoot.getFrames(); xChildContainer.append(xFrame); // Make some further initializations on frame and window. xWindow.setVisible(true); xFrame.setName(sName); } catch(com.sun.star.uno.RuntimeException exRuntime) { // Any UNO method of this scope can throw this exception. // So the frame can be already created and he must be freed // correctly. May be he was inserted into the desktop tree too ... if(xFrame!=null) { // Try to dispose the frame. He should deregister himself at the desktop object // and free all internal used resources (e.g. the container window) automatically. // It's possible to do that here - because frame has no component inside yet. // So nobody can disagree with that. // After the dispose() call forget all references to this frame and let him die. // If a new exception will occur ... no generell solution exist then. // Nobody can guarantee if next call will work or not. com.sun.star.lang.XComponent xComponent = UnoRuntime.queryInterface( com.sun.star.lang.XComponent.class, xFrame); xComponent.dispose(); xComponent = null; xFrame = null; } } catch(com.sun.star.uno.Exception exUno) { // "createInstance()" method of used service manager can throw it. // If it occurred during creation of desktop service the frame already was created. // Free it by decresing his refcount. Changes on the desktop tree couldn't exist. // Without the desktop service that wasn't possible. So no further rollbacks must follow. if(xFrame!=null) { com.sun.star.lang.XComponent xComponent = UnoRuntime.queryInterface( com.sun.star.lang.XComponent.class, xFrame); xComponent.dispose(); xComponent = null; xFrame = null; } } return xFrame; } /** * Dispatch an URL to given frame. * Caller can register himself for following status events for dispatched * URL too. But nobody guarantee that such notifications will occur. * (see dispatchWithNotification() if you interest on that) * The returned dispatch object should be hold alive by caller * till he deosn't need it any longer. Otherwise the dispatcher can(!) * die by decreasing his refcount. * * @param xFrame frame which should be the target of this dispatch * @param aURL full parsed and converted office URL for dispatch * @param lProperties optional arguments for dispatch * @param xListener optional listener which is registered automatically for status events * (Note: Deregistration is part of this listener himself!) * * @return [XDispatch] It's the used dispatch object and can be used for deregistration of an optional listener. * Otherwhise caller can ignore it. */ public static com.sun.star.frame.XDispatch execute(com.sun.star.frame.XFrame xFrame , com.sun.star.util.URL aURL , com.sun.star.beans.PropertyValue[] lProperties, com.sun.star.frame.XStatusListener xListener ) { com.sun.star.frame.XDispatch xDispatcher = null; try { // Query the frame for right interface which provides access to all available dispatch objects. com.sun.star.frame.XDispatchProvider xProvider = UnoRuntime.queryInterface( com.sun.star.frame.XDispatchProvider.class, xFrame); // Ask himn for right dispatch object for given URL. // Force given frame as target for following dispatch by using "". // It means the same like "_self". xDispatcher = xProvider.queryDispatch(aURL,"",0); // Dispatch the URL into the frame. if(xDispatcher!=null) { if(xListener!=null) xDispatcher.addStatusListener(xListener,aURL); xDispatcher.dispatch(aURL,lProperties); } } catch(com.sun.star.uno.RuntimeException exUno) { // Any UNO method of this scope can throw this exception. // But there will be nothing to do then - because // we haven't changed anything inside the remote objects // except method "addStatusListener(). // But in this case the source of this exception has to // rollback all his operations. There is no chance to // make anything right then. // Reset the return value to a default - that's it. exUno.printStackTrace(); xDispatcher = null; } return xDispatcher; } /** * Dispatch an URL to given frame. * Caller can register himself for following result events for dispatched * URL too. Notifications are guaranteed (instead of dispatch()) * Returning of the dispatch object isn't necessary. * Nobody must hold it alive longer the dispatch needs. * * @param xFrame frame which should be the target of this dispatch * @param aURL full parsed and converted office URL for dispatch * @param lProperties optional arguments for dispatch * @param xListener optional listener which is registered automatically for status events * (Note: Deregistration is not supported. Dispatcher does it automatically.) */ public static void executeWithNotification(com.sun.star.frame.XFrame xFrame , com.sun.star.util.URL aURL , com.sun.star.beans.PropertyValue[] lProperties, com.sun.star.frame.XDispatchResultListener xListener ) { try { // Query the frame for right interface which provides access to all available dispatch objects. com.sun.star.frame.XDispatchProvider xProvider = UnoRuntime.queryInterface( com.sun.star.frame.XDispatchProvider.class, xFrame); // Ask himn for right dispatch object for given URL. // Force THIS frame as target for following dispatch. // Attention: The interface XNotifyingDispatch is an optional one! com.sun.star.frame.XDispatch xDispatcher = xProvider.queryDispatch(aURL,"",0); com.sun.star.frame.XNotifyingDispatch xNotifyingDispatcher = UnoRuntime.queryInterface( com.sun.star.frame.XNotifyingDispatch.class, xDispatcher); // Dispatch the URL. if(xNotifyingDispatcher!=null) xNotifyingDispatcher.dispatchWithNotification(aURL,lProperties,xListener); } catch(com.sun.star.uno.RuntimeException exUno) { // Any UNO method of this scope can throw this exception. // But there is nothing we can do then. exUno.printStackTrace(); } } /** * Load document specified by an URL into given frame synchronously. * The result of this operation will be the loaded document for success * or null if loading failed. * * @param xFrame frame which should be the target of this load call * @param sURL unparsed URL for loading * @param lProperties optional arguments * * @return [XComponent] the loaded document for success or null if it's failed */ public static com.sun.star.lang.XComponent loadDocument( com.sun.star.frame.XFrame xFrame, String sURL, com.sun.star.beans.PropertyValue[] lProperties) { com.sun.star.lang.XComponent xDocument = null; String sOldName = null; try { com.sun.star.uno.XComponentContext xCtx = OfficeConnect.getOfficeContext(); // First prepare frame for loading // We must address it inside the frame tree without any complications. // So we set an unambigous (we hope it) name and use it later. // Don't forget to reset original name after that. sOldName = xFrame.getName(); String sTarget = "odk_officedev_desk"; xFrame.setName(sTarget); // Get access to the global component loader of the office // for synchronous loading the document. com.sun.star.frame.XComponentLoader xLoader = UnoRuntime.queryInterface( com.sun.star.frame.XComponentLoader.class, xCtx.getServiceManager().createInstanceWithContext( "com.sun.star.frame.Desktop", xCtx)); // Load the document into the target frame by using his name and // special search flags. xDocument = xLoader.loadComponentFromURL( sURL, sTarget, com.sun.star.frame.FrameSearchFlag.CHILDREN, lProperties); // dont forget to restore old frame name ... xFrame.setName(sOldName); } catch(com.sun.star.io.IOException exIO) { // Can be thrown by "loadComponentFromURL()" call. // The only thing we should do then is to reset changed frame name! exIO.printStackTrace(); xDocument = null; if(sOldName!=null) xFrame.setName(sOldName); } catch(com.sun.star.lang.IllegalArgumentException exIllegal) { // Can be thrown by "loadComponentFromURL()" call. // The only thing we should do then is to reset changed frame name! exIllegal.printStackTrace(); xDocument = null; if(sOldName!=null) xFrame.setName(sOldName); } catch(com.sun.star.uno.RuntimeException exRuntime) { // Any UNO method of this scope can throw this exception. // The only thing we can try(!) is to reset changed frame name. exRuntime.printStackTrace(); xDocument = null; if(sOldName!=null) xFrame.setName(sOldName); } catch(com.sun.star.uno.Exception exUno) { // "createInstance()" method of used service manager can throw it. // The only thing we should do then is to reset changed frame name! exUno.printStackTrace(); xDocument = null; if(sOldName!=null) xFrame.setName(sOldName); } return xDocument; } /** * Save currently loaded document of given frame. * * @param xDocument document for saving changes */ public static void saveDocument(com.sun.star.lang.XComponent xDocument) { try { // Check for supported model functionality. // Normaly the application documents (text, spreadsheet ...) do so // but some other ones (e.g. db components) doesn't do that. // They can't be save then. com.sun.star.frame.XModel xModel = UnoRuntime.queryInterface( com.sun.star.frame.XModel.class, xDocument); if(xModel!=null) { // Check for modifications => break save process if there is nothing to do. com.sun.star.util.XModifiable xModified = UnoRuntime.queryInterface( com.sun.star.util.XModifiable.class, xModel); if(xModified.isModified()==true) { com.sun.star.frame.XStorable xStore = UnoRuntime.queryInterface( com.sun.star.frame.XStorable.class, xModel); xStore.store(); } } } catch(com.sun.star.io.IOException exIO) { // Can be thrown by "store()" call. // But there is nothing we can do then. exIO.printStackTrace(); } catch(com.sun.star.uno.RuntimeException exUno) { // Any UNO method of this scope can throw this exception. // But there is nothing we can do then. exUno.printStackTrace(); } } /** * It try to export given document in HTML format. * Current document will be converted to HTML and moved to new place on disk. * A "new" file will be created by given URL (may be overwritten * if it already exist). Right filter will be used automatically if factory of * this document support it. If no valid filter can be found for export, * nothing will be done here. * * @param xDocument document which should be exported * @param sURL target URL for converted document */ public static void saveAsHTML(com.sun.star.lang.XComponent xDocument, String sURL ) { try { // First detect factory of this document. // Ask for the supported service name of this document. // If information is available it can be used to find out wich // filter exist for HTML export. Normaly this filter should be searched // inside the filter configuration but this little demo doesn't do so. // (see service com.sun.star.document.FilterFactory for further // information too) // Well known filter names are used directly. They must exist in current // office installation. Otherwise this code will fail. But to prevent // this code against missing filters it check for existing state of it. com.sun.star.lang.XServiceInfo xInfo = UnoRuntime.queryInterface(com.sun.star.lang.XServiceInfo.class, xDocument); if(xInfo!=null) { // Find out possible filter name. String sFilter = null; if(xInfo.supportsService("com.sun.star.text.TextDocument")==true) sFilter = new String("HTML (StarWriter)"); else if(xInfo.supportsService("com.sun.star.text.WebDocument")==true) sFilter = new String("HTML"); else if(xInfo.supportsService("com.sun.star.sheet.SpreadsheetDocument")==true) sFilter = new String("HTML (StarCalc)"); // Check for existing state of this filter. if(sFilter!=null) { com.sun.star.uno.XComponentContext xCtx = OfficeConnect.getOfficeContext(); com.sun.star.container.XNameAccess xFilterContainer = UnoRuntime.queryInterface( com.sun.star.container.XNameAccess.class, xCtx.getServiceManager().createInstanceWithContext( "com.sun.star.document.FilterFactory", xCtx)); if(xFilterContainer.hasByName(sFilter)==false) sFilter=null; } // Use this filter for export. if(sFilter!=null) { // Export can be forced by saving the document and using a // special filter name which can write needed format. Build // necessary argument list now. // Use special flag "Overwrite" too, to prevent operation // against possible exceptions, if file already exist. com.sun.star.beans.PropertyValue[] lProperties = new com.sun.star.beans.PropertyValue[2]; lProperties[0] = new com.sun.star.beans.PropertyValue(); lProperties[0].Name = "FilterName"; lProperties[0].Value = sFilter; lProperties[1] = new com.sun.star.beans.PropertyValue(); lProperties[1].Name = "Overwrite"; lProperties[1].Value = Boolean.TRUE; com.sun.star.frame.XStorable xStore = UnoRuntime.queryInterface( com.sun.star.frame.XStorable.class, xDocument); xStore.storeAsURL(sURL,lProperties); } } } catch(com.sun.star.io.IOException exIO) { // Can be thrown by "store()" call. // Do nothing then. Saving failed - that's it. exIO.printStackTrace(); } catch(com.sun.star.uno.RuntimeException exRuntime) { // Can be thrown by any uno call. // Do nothing here. Saving failed - that's it. exRuntime.printStackTrace(); } catch(com.sun.star.uno.Exception exUno) { // Can be thrown by "createInstance()" call of service manager. // Do nothing here. Saving failed - that's it. exUno.printStackTrace(); } } /** * Try to close the document without any saving of modifications. * We can try it only! Controller and/or model of this document * can disagree with that. But mostly they doesn't do so. * * @param xDocument document which should be clcosed */ public static void closeDocument(com.sun.star.lang.XComponent xDocument) { try { // Check supported functionality of the document (model or controller). com.sun.star.frame.XModel xModel = UnoRuntime.queryInterface( com.sun.star.frame.XModel.class, xDocument); if(xModel!=null) { // It's a full featured office document. // Reset the modify state of it and close it. // Note: Model can disgree by throwing a veto exception. com.sun.star.util.XModifiable xModify = UnoRuntime.queryInterface( com.sun.star.util.XModifiable.class, xModel); xModify.setModified(false); xDocument.dispose(); } else { // It's a document which supports a controller .. or may by a pure // window only. If it's at least a controller - we can try to // suspend him. But - he can disagree with that! com.sun.star.frame.XController xController = UnoRuntime.queryInterface( com.sun.star.frame.XController.class, xDocument); if(xController!=null) { if(xController.suspend(true)==true) { // Note: Don't dispose the controller - destroy the frame // to make it right! com.sun.star.frame.XFrame xFrame = xController.getFrame(); xFrame.dispose(); } } } } catch(com.sun.star.beans.PropertyVetoException exVeto) { // Can be thrown by "setModified()" call on model. // He disagree with our request. // But there is nothing to do then. Following "dispose()" call wasn't // never called (because we catch it before). Closing failed -that's it. exVeto.printStackTrace(); } catch(com.sun.star.lang.DisposedException exDisposed) { // If an UNO object was already disposed before - he throw this special // runtime exception. Of course every UNO call must be look for that - // but it's a question of error handling. // For demonstration this exception is handled here. exDisposed.printStackTrace(); } catch(com.sun.star.uno.RuntimeException exRuntime) { // Every uno call can throw that. // Do nothing - closing failed - that's it. exRuntime.printStackTrace(); } } /** * Try to close the frame instead of the document. * It shows the possible interface to do so. * * @param xFrame * frame which should be clcosed * * @return in case frame could be closed * otherwise */ public static boolean closeFrame(com.sun.star.frame.XFrame xFrame) { boolean bClosed = false; try { // first try the new way: use new interface XCloseable // It replace the deprecated XTask::close() and should be preferred ... // if it can be queried. com.sun.star.util.XCloseable xCloseable = UnoRuntime.queryInterface( com.sun.star.util.XCloseable.class, xFrame); if (xCloseable!=null) { // We deliver the owner ship of this frame not to the (possible) // source which throw a CloseVetoException. We whishto have it // under our own control. try { xCloseable.close(false); bClosed = true; } catch( com.sun.star.util.CloseVetoException exVeto ) { bClosed = false; } } else { // OK: the new way isn't possible. Try the old one. com.sun.star.frame.XTask xTask = UnoRuntime.queryInterface(com.sun.star.frame.XTask.class, xFrame); if (xTask!=null) { // return value doesn't interest here. Because // we forget this task ... bClosed = xTask.close(); } } } catch (com.sun.star.lang.DisposedException exDisposed) { // Of course - this task can be already dead - means disposed. // But for us it's not important. Because we tried to close it too. // And "already disposed" or "closed" should be the same ... bClosed = true; } return bClosed; } /** * Try to find an unique frame name, which isn't currently used inside * remote office instance. Because we create top level frames * only, it's enough to check the names of existing child frames on the * desktop only. * * @return [String] * should represent an unique frame name, which currently isn't * used inside the remote office frame tree * (Couldn't guaranteed for a real multithreaded environment. * But we try it ...) */ private static final String BASEFRAMENAME = "Desk View "; public static String getUniqueFrameName() { String sName = null; com.sun.star.uno.XComponentContext xCtx = OfficeConnect.getOfficeContext(); try { com.sun.star.frame.XFramesSupplier xSupplier = UnoRuntime.queryInterface( com.sun.star.frame.XFramesSupplier.class, xCtx.getServiceManager().createInstanceWithContext( "com.sun.star.frame.Desktop", xCtx)); com.sun.star.container.XIndexAccess xContainer = UnoRuntime.queryInterface( com.sun.star.container.XIndexAccess.class, xSupplier.getFrames()); int nCount = xContainer.getCount(); for (int i=0; i * dialog is opened in "file open" mode - * otherwise in "file save" mode. */ public static String askUserForFileURL(Component aParent,boolean bOpen) { String sFileURL = null; int nDecision = JFileChooser.CANCEL_OPTION; JFileChooser aChooser = null; // set last visited directory on new file chosser // (if this information is available) if( maLastDir==null ) aChooser = new JFileChooser(); else aChooser = new JFileChooser(maLastDir); // decide between file open/save dialog if( bOpen==true ) nDecision = aChooser.showOpenDialog(aParent); else nDecision = aChooser.showSaveDialog(aParent); // react for "OK" result only if(nDecision == JFileChooser.APPROVE_OPTION) { // save current directory as last visited one maLastDir = aChooser.getCurrentDirectory(); // get file URL from the dialog try { sFileURL = aChooser.getSelectedFile().toURI().toURL().toExternalForm(); } catch( MalformedURLException ex ) { ex.printStackTrace(); sFileURL = null; } // problem of java: file URL's are coded with 1 slash instead of 3 ones! // => correct this problem first, otherwise office can't use these URL's if( ( sFileURL !=null ) && ( sFileURL.startsWith("file:/") ==true ) && ( sFileURL.startsWith("file://")==false ) ) { StringBuffer sWorkBuffer = new StringBuffer(sFileURL); sWorkBuffer.insert(6,"//"); sFileURL = sWorkBuffer.toString(); } } return sFileURL; } /** * @member maLastDir save the last visited directory of used file open/save dialog * @member mnViewCount we try to set unique names on every frame we create (that's why we must count it) */ private static File maLastDir = null; private static int mnViewCount = 0 ; }