ag.ion.noa4e.ui.operations.LoadDocumentOperation.java Source code

Java tutorial

Introduction

Here is the source code for ag.ion.noa4e.ui.operations.LoadDocumentOperation.java

Source

/****************************************************************************
 *                                                                          *
 * NOAText_jsl based upon NOA (Nice Office Access) / noa-libre              *
 * ------------------------------------------------------------------------ *
 *                                                                          *
 * The Contents of this file are made available subject to                  *
 * the terms of GNU General Public License Version 2.1                      *
 *                                                                          * 
 * GNU General Public License Version 2.1                                   *
 * ======================================================================== *
 * Portions Copyright 2012 by Joerg Sigle                                   *
 * Copyright 2003-2006 by IOn AG                                            *
 *                                                                          *
 * This program is free software: you can redistribute it and/or modify     *
 * it under the terms of the GNU General Public License as published by     *
 * the Free Software Foundation, either version 2.1 of the License.         *
 *                                                                          *
 *  This program is distributed in the hope that it will be useful,         *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of          *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
 *  GNU General Public License for more details.                            *
 *                                                                          *
 *  You should have received a copy of the GNU General Public License       *
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
 *                                                                          *
 * Contact us:                                                              *
 *  http://www.jsigle.com                                                   *
 *  http://www.ql-recorder.com                                              *
 *  http://code.google.com/p/noa-libre                                      *
 *  http://www.ion.ag                                                       *
 *  http://ubion.ion.ag                                                     *
 *  info@ion.ag                                                             *
 *                                                                          *
 * Please note: Previously, versions of the NOA library provided by         *
 * www.ion.ag and the noa-libre project carried a licensing remark          *
 * that made them available under the LGPL. However, they include portions  *
 * obtained from the YaBS project, licensed under GPL. Consequently, NOA    *
 * should have been licensed under the GPL, not LGPL, given that no special *
 * permission of the authors of YaBS for LGPL licensing had been obtained.  *
 * To point out the possible problem, I'm providing the files where I added *
 * contributions under the GPL for now. This move is always allowed for     *
 * LPGL licensed material. 20120623js                                       * 
 *                                                                          *
 ****************************************************************************/

/****************************************************************************
 * To Do:
 * See experiment / comments by Joerg Sigle below.
 * Review what's happening inside called code (i.e. in OpenOffice/LibreOffice
 * libraries); why does it all work when the office window is not generated
 * inside a frame, but on its own? Apply necessary corrections so that the
 * same grade of robustness is achieved in a frame.
 * Possibly, this version of the library should get a new revision number, currently used is 11672.
 ****************************************************************************/

/*
 * Last changes made by $Author: jsigle $, $Date: 2012-06-23 14:38:00 +0100 (Su, 23 Jun 2012) $
 */
package ag.ion.noa4e.ui.operations;

import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;

import com.sun.star.beans.XPropertySet; //20120222js: To support disabling menus items and open dialogs which would cause the Elexis/OO to hang
import com.sun.star.frame.XFrame; //20120222js: To support disabling menus items and open dialogs which would cause the Elexis/OO to hang
import com.sun.star.frame.XLayoutManager; //20120222js: To support disabling menus items and open dialogs which would cause the Elexis/OO to hang
import com.sun.star.uno.UnoRuntime; //20120222js: To support disabling menus items and open dialogs which would cause the Elexis/OO to hang

import ag.ion.bion.officelayer.application.IOfficeApplication;
import ag.ion.bion.officelayer.desktop.GlobalCommands; //20120222js: To support disabling menus items and open dialogs which would cause the Elexis/OO to hang
import ag.ion.bion.officelayer.desktop.IFrame;
import ag.ion.bion.officelayer.document.IDocument;
import ag.ion.bion.officelayer.document.IDocumentDescriptor;
import ag.ion.bion.officelayer.document.IDocumentService; //20120222js: To support disabling menus items and open dialogs which would cause the Elexis/OO to hang
import ag.ion.noa.frame.ILayoutManager; //20120222js: To support disabling menus items and open dialogs which would cause the Elexis/OO to hang
import ag.ion.noa4e.internal.ui.preferences.LocalOfficeApplicationPreferencesPage; //20130310js: To support control of js threaded watchdog from NOAText_jsl preferences dialog.

/**
 * Operation in order to load a OpenOffice.org document.
 * 
 * @author Andreas Brker
 * @version $Revision: 11672 $
 */
public class LoadDocumentOperation implements IRunnableWithProgress {

    private IOfficeApplication officeApplication = null;
    private IFrame frame = null;
    private IDocumentDescriptor documentDescriptor = null;

    private String documentType = null;

    private URL url = null;

    private InputStream inputStream = null;

    private boolean isSubTask = false;
    private boolean updateProgressMonitor = true;
    private boolean useStream = false;

    private InternalThread internalThread = null;

    // ----------------------------------------------------------------------------
    /**
     * Internal thread class in order load a a OpenOffice.org text document.
     * 
     * @author Andreas Brker
     */
    private class InternalThread extends Thread {

        private Exception exception = null;

        private IDocument document = null;

        private boolean done = false;

        // ----------------------------------------------------------------------------
        /**
         * Executes thread logic.
         * 
         * Joerg Sigle added code for progress monitoring, to examine the stability problems observed in Elexis,
         * and to improve stability by removing less desired menu options, by closing dialogs, and by docking undocked toolbars,
         * as well as comprehensive comments on available and tested commands and results etc.
         * 
         * @author Joerg Sigle
         * @date 22.02.2012
         * 
         * @author Andreas Brker
         */
        public void run() {
            System.out.println("LoadDocumentOperation: ***************************");
            System.out.println("LoadDocumentOperation: InternalThread: run: begins");
            System.out.println("LoadDocumentOperation: ***************************");
            try {

                System.out.println(
                        "LoadDocumentOperation: InternalThread: run: Trying to do work... Do we already know have a valid frame?");
                if (frame == null)
                    System.out.println("LoadDocumentOperation: InternalThread: run: frame==null");
                else
                    System.out.println("LoadDocumentOperation: InternalThread: run: frame==" + frame.toString());

                if (useStream || inputStream != null) {
                    System.out.println(
                            "LoadDocumentOperation: InternalThread: run: useStream || inputStream != null  --- opening a document from an inputStream");
                    InputStream inputStream = null;
                    if (LoadDocumentOperation.this.inputStream != null)
                        inputStream = LoadDocumentOperation.this.inputStream;
                    else
                        inputStream = url.openStream();

                    //20130219js noatext_jsl 1.4.7:
                    //These lines of code here are apparently never executed, at least when I open an existing Document.
                    //So for debugging, it makes NO sense to replace the following line loading a document into a frame
                    //by a corresponding line that would alternatively load it into a new window (but look for TAKE 2 below there it works):
                    //
                    //System.out.println("LoadDocumentOperation: InternalThread: run: ********************************************************************");
                    //System.out.println("LoadDocumentOperation: InternalThread: run: DELIBERATELY LOADING NOT INTO FRAME FOR DEBUGGING PURPOSES - TAKE 1.");
                    //System.out.println("LoadDocumentOperation: InternalThread: run: ********************************************************************");
                    //
                    if (frame != null) {
                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: PRE1 - about to load a document from inputStream into the frame");
                        // The original line which is probably not executed, so its replacing does not cause an effect for debugging:
                        // ORIGINAL LINE: MAY BE DISABLED FOR DEBUGGING ONLY: 
                        document = officeApplication.getDocumentService().loadDocument(frame, inputStream,
                                documentDescriptor);
                        // ALTERNATIVE LINE: WILL NOT LOAD TO A FRAME BUT INTO A NEW WINDOW - FOR DEBUGGING ONLY:
                        // document = officeApplication.getDocumentService().loadDocument(inputStream, documentDescriptor);
                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: POST1 - loaded a document from inputStream into the frame");
                    } else {
                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: PRE1 FALLBACK - about to load a document from inputStream NOT into a frame, but into a new window");
                        document = officeApplication.getDocumentService().loadDocument(inputStream,
                                documentDescriptor);
                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: POST1 FALLBACK - loaded a document from inputStream NOT into a frame, but into a new window");
                    }

                    try {
                        inputStream.close();
                    } catch (Throwable throwable) {
                        // do not consume
                    }
                } else {
                    System.out.println(
                            "LoadDocumentOperation: InternalThread: run: NOT (useStream || inputStream != null)  --- opening a document from a file (or a URL)");
                    System.out
                            .println("LoadDocumentOperation: InternalThread: run: Status before loadDocument()...");

                    if (officeApplication == null)
                        System.out.println("LoadDocumentOperation: InternalThread: run: officeApplication==null");
                    else
                        System.out.println("LoadDocumentOperation: InternalThread: run: officeApplication="
                                + officeApplication.toString());

                    if (url == null)
                        System.out.println("LoadDocumentOperation: InternalThread: run: url==null");
                    else
                        System.out.println("LoadDocumentOperation: InternalThread: run: url=" + url.toString());

                    if (frame == null)
                        System.out.println("LoadDocumentOperation: InternalThread: run: frame==null");
                    else
                        System.out.println("LoadDocumentOperation: InternalThread: run: frame=" + frame.toString());

                    if (documentDescriptor == null)
                        System.out.println("LoadDocumentOperation: InternalThread: run: documentDescriptor==null");
                    else
                        System.out.println("LoadDocumentOperation: InternalThread: run: documentDescriptor="
                                + documentDescriptor.toString());

                    // 201302200257js:
                    // Wenn ich *nachfolgend* (siehe TAKE 2) nicht korrekt in einen frame lade,
                    // sondern in ein (implizites, wenn kein Ziel-Frame genannt wird) neues Fenster -
                    // dann macht das in Linux den Unterschied, ob das Dokument sichtbar erscheint, oder nicht.
                    // Will sagen: In ein neues Fenster kann ich einen Brief zum Bearbeiten so laden, dass es sichtbar und editierbaer wird,
                    // aber nicht in einen Frame - da wrden zwar die Log Meldungen alle ganz normal sein, aber statt dass Inhalt und Editor
                    // erscheinen, wrde der Frame erst mal nur grau bleiben. Das nur in Linux, nicht in Windows.

                    // 201202222250js:
                    // Wenn ich immer NICHT nach frame lade, dann steht Elexis nach dem Beginn des Ladens, wenn in OO ein Fenster wie
                    // Druckformatvorlage offen war, zwar auch - aber nach dem Beenden von Elexis (mit Fehler: Elexis reagiert nicht)
                    // folgt dann kein identischer Abbruch von OO, sondern OO ist mit dem Dokument als eigenes Fenster
                    // vorhanden, und das offene Druckformatvorlage-Fenster auch.
                    // Also vermutlich will das Druckformatvorlagen-Fenster vor allem nicht in den Frame?
                    // Oder, das nicht binden an den Frame schtzt das halboffene OpenOffice vor den Folgen des Abschusses des
                    // stehenden Elexis?
                    System.out.println(
                            "LoadDocumentOperation: InternalThread: run: officeApplication.getDesktopService()="
                                    + officeApplication.getDesktopService());
                    System.out.println(
                            "LoadDocumentOperation: InternalThread: run: officeApplication.getDesktopService().getFramesCount()="
                                    + officeApplication.getDesktopService().getFramesCount());

                    if (officeApplication.getDesktopService().getFramesCount() > 1) {
                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: WARNING: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: WARNING: getFramesCount()>1, so you probably have multiple (invisible) Office frames open!");
                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: WARNING: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
                    }
                    ;

                    // Es gibt unter getApplicationInfo() auch Methoden, um
                    // einzelne Infos oder z.B. die Info, ob der initial config
                    // wizard gelaufen ist etc. herauszulesen:
                    // System.out.println("LoadDocumentOperation: InternalThread: run: officeApplication.getApplicationInfo().dumpInfo()=");
                    // officeApplication.getApplicationInfo().dumpInfo();

                    if (frame != null) {

                        System.out.println();
                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: TO DO: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: TO DO: Please consider moving the disableDispatch and layoutManager stuff to a better place!");
                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: TO DO: (Or maybe not - LayoutManager stuff only effective after the docLoad?)");
                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: TO DO: (Maybe due to some \"Load settings with document...\" option, though.)");
                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: TO DO: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");

                        // This could be used if we wouldn't know the frame
                        // already:
                        // IFrame frame = document.getFrame();

                        // The following tweaks alltogether do NOT suffice to
                        // avoid or close all floating dialog windows,
                        // which might be (re-)open(ed) when OpenOffice starts
                        // inside Elexis, and thereby halt the
                        // OpenOffice within Elexis startup for some reason or
                        // another (probably because the main OO window
                        // cannot be localized as expected, or its services are
                        // unavailable??/unaccessible?, while another dialog is
                        // there).
                        // Testcase: Select Patient. Add new letter for him
                        // using any template. Go to top left position, insert
                        // table.
                        // Put text cursor into that table - will open table
                        // dialog. Close "Briefe" view (thereby saving the
                        // letter to
                        // the database in exactly this state).
                        // Reopen the letter - this will redisplay the letter,
                        // the table, with the cursor inside, and thus also
                        // create the table dialog immediately. No matter
                        // whether it couldn't be closed by the following
                        // commands,
                        // or not - it hinders the continued startup. If in the
                        // same elexis as before, it might even still be seen
                        // blinking up before the whole Elexis/OpenOffice frame
                        // stalls. 201202232313js

                        // 20120222js: Added this in, adopted from the examples:
                        // http://www.usegroup.de/software/noa/index.php/Hello_World_in_SWT/JFace
                        // http://ubion.ion.ag/mainForumFolder/oiep_forum/0053/
                        // Now it is time to disable two commands in the frame
                        // This comes from snippet14

                        frame.disableDispatch(GlobalCommands.NEW_DOCUMENT);
                        // frame.disableDispatch(GlobalCommands.NEW_MENU); ??js
                        frame.disableDispatch(GlobalCommands.CLOSE_DOCUMENT);
                        frame.disableDispatch(GlobalCommands.QUIT_APPLICATION);
                        // frame.disableDispatch(GlobalCommands.PRINT_DOCUMENT);
                        // frame.disableDispatch(GlobalCommands.PRINT_DOCUMENT_DIRECT);

                        // The following commands are not bad as such - BUT, if
                        // the dialogs they open remain open throughout the
                        // closing of OpenOffice,
                        // they will remain open, be opened again when it is
                        // next started, and thereby cause the Elexis/OO bridge
                        // to hang when opening a doc.
                        // (Just like almost any OpenOffice dialog open on
                        // startup time)
                        // So I inhibit the dialog opening commands for dialogs
                        // which will probably NOT be used within OpenOffice.
                        frame.disableDispatch(GlobalCommands.OPEN_HYPERLINK_DIALOG);
                        frame.disableDispatch(GlobalCommands.EDIT_HYPERLINK);
                        frame.disableDispatch(GlobalCommands.OPEN_DRAW_TOOLBAR);
                        frame.disableDispatch(GlobalCommands.OPEN_NAVIGATOR);
                        frame.disableDispatch(GlobalCommands.OPEN_GALLERY);
                        frame.disableDispatch(GlobalCommands.OPEN_DATASOURCES);
                        frame.disableDispatch(GlobalCommands.OPEN_STYLE_SHEET); // Schtzt
                        // NICHT
                        // vor
                        // bereits
                        // extern
                        // geffnetem
                        // F11
                        // Formatvorlagendialog
                        // frame.disableDispatch(GlobalCommands.OPEN_HELP);
                        frame.disableDispatch(GlobalCommands.OPEN_ASSISTS);
                        // frame.disableDispatch(GlobalCommands.OPEN_VERSION_DIALOG);
                        // //Diese hier stren vielleicht das Wiederffnen,
                        // frame.disableDispatch(GlobalCommands.OPEN_OTHER_FIELDS_DIALOG);
                        // //enthalten aber an sich sinnvolle Funktionalitten,
                        // frame.disableDispatch(GlobalCommands.OPEN_INSERT_SCRIPT_DIALOG);
                        // //bzw. solche, die hoffentlich nur Leute verwenden,
                        // frame.disableDispatch(GlobalCommands.OPEN_FONT_DIALOG);
                        // //welche sich im Fall eines Stehenbleibens zu helfen
                        // wissen.
                        // Es gibt noch einige weitere in GlobalCommands; und
                        // vermutlich noch weitere via uno (siehe, woher
                        // GlobalCommands sich speist).
                        // Die lasse ich jetzt aber mal unbesehen stehen.

                        frame.updateDispatches(); // 201202230410js: Only
                        // thereafter, the
                        // disableDispatch() has
                        // some effect!

                        // Das folgende wirkt hier oben anscheinend nicht bis
                        // nach dem loadDocument():
                        ILayoutManager layoutManager = frame.getLayoutManager();

                        layoutManager.hideAll(); // 201202230412js: This becomes
                        // effective immediately.
                        // But maybe it doesn't help
                        // before the load document!
                        // Maybe it only affects the
                        // doc that will immed be
                        // unloaded.

                        /*
                         * layoutManager.showElement(ILayoutManager.);
                         * layoutManager.showElement(ILayoutManager.);
                         * layoutManager.showElement(ILayoutManager.); public
                         * static String[] ALL_BARS_URLS = new String[] {
                         * URL_MENUBAR, URL_STATUSBAR, URL_TOOLBAR,
                         * URL_TOOLBAR_ALIGNMENTBAR, URL_TOOLBAR_ARROWSHAPES,
                         * URL_TOOLBAR_BASICSHAPES, URL_TOOLBAR_CALLOUTSHAPES,
                         * URL_TOOLBAR_DRAWBAR, URL_TOOLBAR_DRAWOBJECTBAR,
                         * URL_TOOLBAR_EXTRUSIONOBJECTBAR,
                         * URL_TOOLBAR_FONTWORKOBJECTBAR,
                         * URL_TOOLBAR_FONTWORKSHAPETYPES,
                         * URL_TOOLBAR_FORMATOBJECTBAR,
                         * URL_TOOLBAR_FORMCONTROLS, URL_TOOLBAR_FORMDESIGN,
                         * URL_TOOLBAR_FORMFILTERBAR,
                         * URL_TOOLBAR_FORMSNAVIGATIONBAR,
                         * URL_TOOLBAR_FORMSOBJECTBAR,
                         * URL_TOOLBAR_FORMSTEXTOBJECTBAR,
                         * URL_TOOLBAR_FULLSCREENBAR,
                         * URL_TOOLBAR_GRAPHICOBJECTBAR, URL_TOOLBAR_INSERTBAR,
                         * URL_TOOLBAR_INSERTCELLSBAR,
                         * URL_TOOLBAR_INSERTOBJECTSBAR,
                         * URL_TOOLBAR_MEDIAOBJECTSBAR,
                         * URL_TOOLBAR_MOREFORMCONTROLS, URL_TOOLBAR_PREVIEWBAR,
                         * URL_TOOLBAR_STANDARDBAR, URL_TOOLBAR_STARSHAPES,
                         * URL_TOOLBAR_SYMBOLSHAPES, URL_TOOLBAR_TEXTOBJECTBAR,
                         * URL_TOOLBAR_VIEWERBAR };
                         */

                        // System.out.println("LoadDocumentOperation: InternalThread: run: WARNING: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
                        // System.out.println("LoadDocumentOperation: InternalThread: run: WARNING: constructNewDocument instead of loadDocument used for debugging purposes!");
                        // System.out.println("LoadDocumentOperation: InternalThread: run: WARNING: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
                        // document =
                        // officeApplication.getDocumentService().constructNewDocument(frame,
                        // IDocument.WRITER, documentDescriptor);

                        XFrame xFrame = frame.getXFrame();
                        XPropertySet xPropSet = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class,
                                xFrame);
                        XLayoutManager xLayoutManager = (XLayoutManager) UnoRuntime
                                .queryInterface(XLayoutManager.class, xPropSet.getPropertyValue("LayoutManager"));
                        xLayoutManager.dockAllWindows(com.sun.star.ui.UIElementType.FLOATINGWINDOW);
                        xLayoutManager.dockAllWindows(com.sun.star.ui.UIElementType.TOOLBAR);
                        xLayoutManager.dockAllWindows(com.sun.star.ui.UIElementType.MENUBAR);
                        xLayoutManager.dockAllWindows(com.sun.star.ui.UIElementType.POPUPMENU);
                        xLayoutManager.dockAllWindows(com.sun.star.ui.UIElementType.STATUSBAR);
                        xLayoutManager.dockAllWindows(com.sun.star.ui.UIElementType.PROGRESSBAR);
                        xLayoutManager.dockAllWindows(com.sun.star.ui.UIElementType.UNKNOWN);
                        // xLayoutManager.dockAllWindows(com.sun.star.ui.UIElementType.TOOLPANEL);

                        // System.out.println("LoadDocumentOperation: xFrame.getName()"+xFrame.getName());

                        // System.out.println("findFrame(\"Formatvorlagen\"):"+xFrame.findFrame("Formatvorlagen",com.sun.star.frame.FrameSearchFlag.ALL).getName());

                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: *******************************************************");
                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: PRE2 - about to load a document from url into the frame");
                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: *******************************************************");

                        // Das hier wrde auch gehen, da loadDocument() eine Methode von IDocumentService ist,
                        // und selbst ein IDocument zurckgibt. Dann gbe es aber keine interims-Debug-Outputs. 
                        // document =
                        // officeApplication.getDocumentService().loadDocument(frame,
                        // url.toString(), documentDescriptor);

                        IDocumentService documentService = officeApplication.getDocumentService();

                        if (documentService == null)
                            System.out
                                    .println("LoadDocumentOperation: InternalThread: run: documentService()==null");
                        else
                            System.out.println("LoadDocumentOperation: InternalThread: run: documentService()="
                                    + documentService.toString());

                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: documentService.MAX_OPENED_DOCS:           "
                                        + documentService.MAX_OPENED_DOCS);
                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: documentService.getCurrentDocumentCount(): "
                                        + documentService.getCurrentDocumentCount());
                        if (documentService.getCurrentDocumentCount() > 1) {
                            System.out.println(
                                    "LoadDocumentOperation: InternalThread: run: WARNING: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
                            System.out.println(
                                    "LoadDocumentOperation: InternalThread: run: WARNING: getCurrentDocumentCount()>1, so you probably have multiple (invisible) Office documents open!");
                            System.out.println(
                                    "LoadDocumentOperation: InternalThread: run: WARNING: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
                        }
                        ;
                        //System.out.println("LoadDocumentOperation: documentService.getCurrentDocuments():     "+documentService.getCurrentDocuments().toString());

                        if (frame == null)
                            System.out.println("LoadDocumentOperation: InternalThread: run: frame==null");
                        else
                            System.out.println(
                                    "LoadDocumentOperation: InternalThread: run: frame=" + frame.toString());

                        if (documentDescriptor == null)
                            System.out.println(
                                    "LoadDocumentOperation: InternalThread: run: documentDescriptor==null");
                        else
                            System.out.println("LoadDocumentOperation: InternalThread: run: documentDescriptor="
                                    + documentDescriptor.toString());

                        //201302200300js:
                        //See comments further above - loading NOT into a frame is for debugging only.
                        //In Linux, this will show an editable document in a new window, whereas loading into a frame
                        //will return only a gray frame without any content or editing abilities
                        //(only the frame name in the tab will appear as expected).

                        //System.out.println("LoadDocumentOperation: InternalThread: run: ********************************************************************");
                        //System.out.println("LoadDocumentOperation: InternalThread: run: DELIBERATELY LOADING NOT INTO FRAME FOR DEBUGGING PURPOSES - TAKE 2.");
                        //System.out.println("LoadDocumentOperation: InternalThread: run: ********************************************************************");

                        // ORIGINAL LINE: MAY BE DISABLED FOR DEBUGGING ONLY: 
                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: ********************************************************************");
                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: CAVE: THIS documentService.loadDocument(frame...) MAY LEAD TO A METHOD THAT EXPECTS XFrame, not frame!!!");
                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: ********************************************************************");
                        document = documentService.loadDocument(frame, url.toString(), documentDescriptor);
                        // ALTERNATIVE LINE: WILL NOT LOAD TO A FRAME BUT INTO A NEW WINDOW - FOR DEBUGGING ONLY:
                        // document = documentService.loadDocument(url.toString(), documentDescriptor);

                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: *************************************************");
                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: POST2 - loaded a document from url into the frame");
                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: *************************************************");

                        // Aus irgendeinem Grunde erscheint das Dokument (in Linux) NICHT in dem Frame mit der in frame bergebenen ID:
                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: frame:                           "
                                        + frame.toString());
                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: frame.getXFrame():               "
                                        + frame.getXFrame().toString());
                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: document.getFrame():             "
                                        + document.getFrame().toString());
                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: document.getFrame().getXFrame(): "
                                        + document.getFrame().getXFrame().toString());
                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: document.getDocumentType():      "
                                        + document.getDocumentType());
                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: document.getLocationURL():       "
                                        + document.getLocationURL().toString());

                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: documentDescriptor.getURL():     "
                                        + documentDescriptor.getURL());
                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: documentDescriptor.getTitle():   "
                                        + documentDescriptor.getTitle());

                        //20130220js MAL SCHAUEN, OB WIR DEN FRAMEINHALT in linux hervorzaubern knnen:
                        //Das hier hilft alles nichts:
                        //document.getFrame().setFocus();
                        //document.getFrame().updateDispatches();
                        //frame.notifyAll();
                        //frame.setFocus();
                        //frame.updateDispatches();
                        //frame.wait();
                        //frame.close(); //Das sorgt dafr, dass das Dokument mit ark geffnet wird - wie nach dem Schliessen des letzten OfficeWindows
                        //document.fireDocumentEvent(IDocument.EVENT_ON_LOAD_DONE);
                        //document.fireDocumentEvent(IDocument.EVENT_ON_LOAD_FINISHED);
                        //document.fireDocumentEvent(IDocument.EVENT_ON_FOCUS);
                        //document.notifyAll();

                        // Das folgende (showElement zumindest) wirkt von weiter
                        // oben NICHT bis nach dem loadDocument() (NOCHMAL
                        // getestet, stimmt!):
                        layoutManager.hideAll(); // 201202230412js: This becomes
                        // effective immediately.
                        // Schtzt gegen offenen
                        // URL_TOOLBAR,
                        // aber leider NICHT gegen
                        // offenen F11
                        // Formatvorlagen Dialog
                        layoutManager.showElement(ILayoutManager.URL_MENUBAR); // ok
                        // und
                        // sinnvoll
                        layoutManager.showElement(ILayoutManager.URL_STATUSBAR); // ok
                        // und
                        // sinnvoll
                        // layoutManager.showElement(ILayoutManager.URL_TOOLBAR);
                        // //fhrt zum Stehenbleiben
                        layoutManager.showElement(ILayoutManager.URL_TOOLBAR_STANDARDBAR); // ok
                        // layoutManager.showElement(ILayoutManager.URL_TOOLBAR_ALIGNMENTBAR);
                        // //ok, aber nicht fr text sondern fr andere objekte
                        // -> eher unntig
                        // layoutManager.showElement(ILayoutManager.URL_TOOLBAR_FONTWORKOBJECTBAR);
                        // //fhrt zum Stehenbleiben
                        // layoutManager.showElement(ILayoutManager.URL_TOOLBAR_FONTWORKSHAPETYPES);
                        // //ok, aber recht leer?
                        // layoutManager.showElement(ILayoutManager.URL_TOOLBAR_FORMATOBJECTBAR);
                        // //ok, aber recht leer?

                        // layoutManager.showElement(ILayoutManager.URL_TOOLBAR_PREVIEWBAR);
                        // //ok, aber dieser und/oder viewerbar in standardbar
                        // enthalten
                        layoutManager.showElement(ILayoutManager.URL_TOOLBAR_TEXTOBJECTBAR); // ok
                        // und
                        // relativ
                        // sinnvoll
                        // layoutManager.showElement(ILayoutManager.URL_TOOLBAR_VIEWERBAR);
                        // //ok, aber dieser und/oder previewbar in standardbar
                        // enthalten

                        xLayoutManager.dockAllWindows(com.sun.star.ui.UIElementType.FLOATINGWINDOW);
                        xLayoutManager.dockAllWindows(com.sun.star.ui.UIElementType.TOOLBAR);
                        xLayoutManager.dockAllWindows(com.sun.star.ui.UIElementType.MENUBAR);
                        xLayoutManager.dockAllWindows(com.sun.star.ui.UIElementType.POPUPMENU);
                        xLayoutManager.dockAllWindows(com.sun.star.ui.UIElementType.STATUSBAR);
                        xLayoutManager.dockAllWindows(com.sun.star.ui.UIElementType.PROGRESSBAR);
                        xLayoutManager.dockAllWindows(com.sun.star.ui.UIElementType.UNKNOWN);

                    } else {
                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: PRE2 FALLBACK - about to load a document from url NOT into a frame, but into a new window");
                        document = officeApplication.getDocumentService().loadDocument(url.toString(),
                                documentDescriptor);
                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: POST2 FALLBACK - loaded a document from url NOT into a frame, but into a new window");
                    }

                    System.out
                            .println("LoadDocumentOperation: InternalThread: run: Status after loadDocument()...");
                    if (document == null)
                        System.out.println("LoadDocumentOperation: InternalThread: run: document==null");
                    else
                        System.out.println(
                                "LoadDocumentOperation: InternalThread: run: document=" + document.toString());

                }
                System.out.println("LoadDocumentOperation: InternalThread: run: ...work has been done.");
                done = true;
            } catch (Exception exception) {
                System.out.println("LoadDocumentOperation: InternalThread: run: WARNING: Caught exception!");
                this.exception = exception;
            } catch (ThreadDeath threadDeath) {
                // do not consume
                System.out.println("LoadDocumentOperation: InternalThread: run: WARNING: Caught threadDeath!");
            }
            System.out.println("LoadDocumentOperation: InternalThread: run: ends");
        }

        // ----------------------------------------------------------------------------
        /**
         * Returns exception. Returns null if no exception was thrown.
         * 
         * @return exception - returns null if no exception was thrown
         * 
         * @author Andreas Brker
         */
        public Exception getException() {
            return exception;
        }

        // ----------------------------------------------------------------------------
        /**
         * Returns loaded document.
         * 
         * @return loaded document
         * 
         * @author Andreas Brker
         */
        public IDocument getDocument() {
            return document;
        }

        // ----------------------------------------------------------------------------
        /**
         * Returns information whether the thread has finished his work.
         * 
         * @return information whether the thread has finished his work
         * 
         * @author Andreas Brker
         */
        public boolean done() {
            if (exception != null)
                return true;
            return done;
        }
        // ----------------------------------------------------------------------------
    }

    // ----------------------------------------------------------------------------

    // ----------------------------------------------------------------------------
    /**
     * Constructs new LoadDocumentOperation.
     * 
     * @param officeApplication
     *            office application to be use
     * @param frame
     *            frame to be used
     * @param url
     *            URL of the document
     * @param documentDescriptor
     *            document descriptor to be used (can be null)
     * 
     * @throws IllegalArgumentException
     *             if the submitted office application, frame or URL is not
     *             valid
     * 
     * @author Andreas Brker
     */
    public LoadDocumentOperation(IOfficeApplication officeApplication, IFrame frame, URL url,
            IDocumentDescriptor documentDescriptor) throws IllegalArgumentException {
        this(null, officeApplication, frame, url, documentDescriptor);
    }

    // ----------------------------------------------------------------------------
    /**
     * Constructs new LoadDocumentOperation.
     * 
     * @param documentType
     *            document type to be loaded (can be null)
     * @param officeApplication
     *            office application to be use
     * @param frame
     *            frame to be used
     * @param url
     *            URL of the document
     * @param documentDescriptor
     *            document descriptor to be used (can be null)
     * 
     * @author Andreas Brker
     */
    public LoadDocumentOperation(String documentType, IOfficeApplication officeApplication, IFrame frame, URL url,
            IDocumentDescriptor documentDescriptor) {

        assert officeApplication != null;

        this.officeApplication = officeApplication;
        this.frame = frame;
        this.url = url;

        this.documentDescriptor = documentDescriptor;
        this.documentType = documentType;
    }

    // ----------------------------------------------------------------------------
    /**
     * Constructs new LoadDocumentOperation.
     * 
     * @param documentType
     *            document type to be loaded (can be null)
     * @param officeApplication
     *            office application to be use
     * @param url
     *            URL of the document
     * @param documentDescriptor
     *            document descriptor to be used (can be null)
     * 
     * @author Andreas Brker
     */
    public LoadDocumentOperation(String documentType, IOfficeApplication officeApplication, URL url,
            IDocumentDescriptor documentDescriptor) {

        assert officeApplication != null;

        this.officeApplication = officeApplication;
        this.url = url;

        this.documentDescriptor = documentDescriptor;
        this.documentType = documentType;
    }

    // ----------------------------------------------------------------------------
    /**
     * Constructs new LoadDocumentOperation.
     * 
     * @param documentType
     *            document type to be loaded (can be null)
     * @param officeApplication
     *            office application to be use
     * @param frame
     *            frame to be used
     * @param inputStream
     *            input stream to be used
     * @param documentDescriptor
     *            document descriptor to be used (can be null)
     * 
     * @author Andreas Brker
     * @date 06.07.2006
     */
    public LoadDocumentOperation(String documentType, IOfficeApplication officeApplication, IFrame frame,
            InputStream inputStream, IDocumentDescriptor documentDescriptor) {
        assert officeApplication != null;
        assert inputStream != null;

        this.officeApplication = officeApplication;
        this.frame = frame;
        this.inputStream = inputStream;

        this.documentDescriptor = documentDescriptor;
        this.documentType = documentType;
    }

    // ----------------------------------------------------------------------------
    /**
     * Constructs new LoadDocumentOperation.
     * 
     * @param officeApplication
     *            office application to be use
     * @param inputStream
     *            input stream to be used
     * @param documentDescriptor
     *            document descriptor to be used (can be null)
     * 
     * @author Andreas Brker
     * @date 10.07.2006
     */
    public LoadDocumentOperation(IOfficeApplication officeApplication, InputStream inputStream,
            IDocumentDescriptor documentDescriptor) {
        this(null, officeApplication, null, inputStream, documentDescriptor);
    }

    // ----------------------------------------------------------------------------
    /**
     * Sets information whether this operation is a sub task.
     * 
     * @param isSubTask
     *            information whether this operation is a sub task
     * 
     * @author Andreas Brker
     */
    public void setIsSubTask(boolean isSubTask) {
        this.isSubTask = isSubTask;
    }

    // ----------------------------------------------------------------------------
    /**
     * Sets information whether the progress monitor should be updated.
     * 
     * @param updateProgressMonitor
     *            information whether the progress monitor should be updated
     * 
     * @author Andreas Brker
     * @date 10.07.2006
     */
    public void setUpdateProgressMonitor(boolean updateProgressMonitor) {
        this.updateProgressMonitor = updateProgressMonitor;
    }

    // ----------------------------------------------------------------------------
    /**
     * Sets information whether the document should be loaded by an input
     * stream.
     * 
     * @param useStream
     *            information whether the document should be loaded by an input
     *            stream
     * 
     * @author Andreas Brker
     * @date 13.06.2006
     */
    public void setUseStream(boolean useStream) {
        this.useStream = useStream;
    }

    // ----------------------------------------------------------------------------
    /**
     * Returns exception. Returns null if no exception was thrown.
     * 
     * @return exception - returns null if no exception was thrown
     * 
     * @author Andreas Brker
     */
    public Exception getException() {
        return internalThread.getException();
    }

    // ----------------------------------------------------------------------------
    /**
     * Returns loaded document. Returns null if no document is available. If a
     * document type was submitted - only a document will be returned if the
     * type of the loaded document matches the submitted type.
     * 
     * @return loaded document or null if no document is available
     * 
     * @author Andreas Brker
     */
    public IDocument getDocument() {
        if (documentType == null)
            return internalThread.getDocument();
        else {
            IDocument document = internalThread.getDocument();
            if (document != null) {
                if (document.getDocumentType().equals(documentType))
                    return document;
            }
            return null;
        }
    }

    // ----------------------------------------------------------------------------
    /**
     * Runs this operation. Progress should be reported to the given progress
     * monitor. This method is usually invoked by an
     * <code>IRunnableContext</code>'s <code>run</code> method, which supplies
     * the progress monitor. A request to cancel the operation should be honored
     * and acknowledged by throwing <code>InterruptedException</code>.
     * 
     * @param progressMonitor
     *            the progress monitor to use to display progress and receive
     *            requests for cancelation
     * 
     * @exception InvocationTargetException
     *                if the run method must propagate a checked exception, it
     *                should wrap it inside an
     *                <code>InvocationTargetException</code>; runtime exceptions
     *                are automatically wrapped in an
     *                <code>InvocationTargetException</code> by the calling
     *                context
     * @exception InterruptedException
     *                if the operation detects a request to cancel, using
     *                <code>IProgressMonitor.isCanceled()</code>, it should exit
     *                by throwing <code>InterruptedException</code>
     * 
      * Joerg Sigle added code for progress monitoring printlns, to examine the stability problems observed in Elexis,
      * and to implement a watchdog timer that will interrupt a hanging loop after a certain time.
      * Empirically, the call to internalThread.destroy(); apparently hits the sweet spot. 
      * It changes the user experience of a completely stalled Elexis/OpenOffice/LibreOffice program
      * into one that may merely be paused for several 10 seconds, and then continue - just as it would be expected.
      * Even when I opened a document with many interactive elements and lots of macro code which would
      * require more than one minute in LibreOffice (for whatever reason, same time if opened outside Elexis),
      * the watchdog would kick in, but the document would still be loaded correctly and work correctly thereafter.
      * So it seems that the watchdog improves the situation and, give the duration I've told it to wait,
      * does not have any disadvantageous effects.
      * In the future, however, I would suggest to review what is actually happening in the interface
      * to greater depth, i.e. down into the OpenOffice/LibreOffice libraries. I haven't done this so far,
      * as I did all the work without funding, with other projects pressing, so I stopped - for now -
      * as son as I saw I had to add the source code of the Office packages into my development system,
      * and my solution found until now would solve the problem in praxi (I have given it several tests).
      * Further details in the comprehensive comments I added below and elsewhere in the library.
      * 
      * @author Joerg Sigle
      * @date 25.02.2012
      * 
     * @author Andreas Brker
     */
    public void run(IProgressMonitor progressMonitor) throws InvocationTargetException, InterruptedException {
        System.out.println("LoadDocumentOperation: run begins");

        System.out.println("LoadDocumentOperation: run 1");
        internalThread = new InternalThread();
        if (isSubTask) {
            if (updateProgressMonitor)
                progressMonitor.subTask(Messages.LoadDocumentOperation_monitor_loading_document);
        } else {
            if (updateProgressMonitor)
                progressMonitor.beginTask(Messages.LoadDocumentOperation_monitor_loading_document, 50);
        }

        System.out.println("LoadDocumentOperation: run 2 - about to start internalThread...");
        //201210220045js I'd like to ensure that the dialog asking the user whether they want to destroy the internal thread
        //is actually displayed. That should be done by the SWTHelper module, but nothing happens while e.g. LibreOffice is busy
        //opening the Status document template and supposedly checking macros or the like. Let me try by lowering the priority
        //of that thread... Es reicht nicht, um whrend LibreOffice opening Status Vorlage einen Dialog erscheinen zu lassen.
        //Erst, wenn das ziemlich / ganz durch ist, erscheint der Dialog. Andererseits... das ist ja ohnehin selbstlimitierend,
        //und ich will *das* eigentlich garnicht unterbrechen. Aber wie ist es denn, wenn ich mal den Formatvorlagen-Dialog
        //hervorhole und undocke? ... ALSO, witzigerweise ist es *genau* wie bentigt - und sogar noch mehr.
        //Testcase: Dokument mit Tabelle erstellen, Tabellen-Toolbar undocken (vor jedem Test neu, weil noatext_jsl den
        //wieder dockt, wenn es ber das stalling hinausgekommen ist, Elexis so schliessen = offener ungedockter Toolbar
        //wird fr dieses Dokument gespeichert. Elexis schliessen, Elexis ffnen, dasselbe Dokument wieder laden (logs anschauen).
        //(Es reicht auch: Dokument ffnen, Tabellen-Toolbar abdocken, Briefe-Fenster schliessen = wird gespeichert, Tabellen-
        //Toolbar abgedockt schliessen, Dokument wieder laden (ohne die Selektion in Briefauswahl verndern zu mssen,
        //Bei diesem Testverfahren braucht man auch Elexis nicht zu beenden.)
        //Folge: Ein Stall (wie erwartet, auch mit LibreOffice 3.6.2.2).
        //Aber: in dem Moment, wo der Watchdog die 40 erreicht, blitzelt es im OO
        //Fenster (kann sein, die Mens erscheinen), und mein Fehlerdialog erscheint. Und - wenn ich dort [Cancel] drcke
        //(aktuell fhrt das dazu, dass das destroy NICHT gesendet wird), dann... verschwindet der Dialog, und...
        //sofort erscheint das geladene Dokument. Die Toolbars werden automatisch gedockt.
        //Das hat diesmal auch keine Nebenwirkungen (beim Status-Dokument wurden ja die Felder ersetzt), also das doc wird
        //dadurch eben NICHT mit null zurckgeliefert, wie wenn ich das destroy abgeschickt htte.
        //Insofern ist: Dialog mit Hinweis auf die mglichen Grnde der Wartezeit zeigen, ohne weitere Auswahlmglichkeit,
        //und OHNE DANACH DESTROY ZU SENDEN fr den weiteren Verlauf wohl das gnstigste!!! 201210220116js
        //(Ich weiss noch nicht, ob das auch die Priority auf lowest braucht - wahrscheinlich nicht - aber stren drfte
        //das wohl kaum, da entweder auf einem Standalone-System die DB-Performance dadurch frei bleibt, oder der Nutzer
        //sonst wohl keine Nachteile haben sollte, bis zu Zeit fr weitere Forschungen lasse ich das also mal so.)
        System.out.println("LoadDocumentOperation: Reading priority of internal thread:");
        System.out.println("LoadDocumentOperation: internalThread.getPriority()=" + internalThread.getPriority());
        System.out.println("LoadDocumentOperation: Changing priority of internal thread:");
        internalThread.setPriority(Thread.MIN_PRIORITY); //1 = THREAD_PRIORITY_LOWEST; 10=THREAD_PRIORITY_TIME_CRITICAL
        System.out.println("LoadDocumentOperation: internalThread.getPriority()=" + internalThread.getPriority());
        internalThread.start();
        System.out.println("LoadDocumentOperation: run 2.1 - internalThread has been started");
        int cyclesWaitedForInternalThreadToComplete = 0;
        while (!internalThread.done()) {
            System.out.println("LoadDocumentOperation: run 2.2 - sleep(500) begins");
            Thread.sleep(500);
            System.out.println("LoadDocumentOperation: run 2.3 - sleep(500) ends");
            if (!isSubTask)
                progressMonitor.worked(1);
            System.out.println("LoadDocumentOperation: run 2.4");
            if (progressMonitor.isCanceled()) {
                /**
                 * This method is deprecated, but ...
                 */
                try {
                    System.out.println(
                            "LoadDocumentOperation: run 2.5 - progressMonitor.isCanceled() has been found.");
                    internalThread.stop();
                } catch (Throwable throwable) {
                    // do not consume - ThreadDeath
                    System.out.println("LoadDocumentOperation: run 2.6 - internalThrread.stop() threw exception.");
                }
                System.out.println("LoadDocumentOperation: run 2.7 - progressMonitor.done() about to occur...");
                progressMonitor.done();
                System.out.println(
                        "LoadDocumentOperation: run 2.8 - about to throw InterruptException() with message...");
                throw new InterruptedException(
                        Messages.LoadDocumentOperation_exception_message_operation_interrupted);
            }
            //201202252105js:
            //Now limit the time we wait for the office application to start.
            //As it may hang (when a floating dialog window like the F11 Formatvorlagen dialog, or table frame properties)
            //is open in OpenOffice/LibreOffice, we will now set a limit for the time we want to wait,
            //and kill the internalThread if that is exceeded.
            //NOTE: This hanging has absolutely NOTHING to do with the removed sleep(3000) below.
            //It has occured forever since oo 2.0.3 in all variants of the noatext interface I now,
            //even after my update to noa 2.2.3 and noa-libre. See my external logs and notes in the code
            //for the results of my debugging.
            //NOTE: On an Intel Core i7 vpro notebook, loading a document takes only 1..2 seconds when it works.
            //To accomodate for significantly slower infrastructure, I'll wait for 20 seconds now before killing the internalThread.
            //NOTE: internalThread is the one that should take care of the loading, which it normally does,
            //after having jumped through zillions of references, methods, procedures etc. within the Java and StarOffice library jungle.
            //NOTE: The NOAText_js and NOAText_jsl implementations of the NOAText plugin, take numerous preconditions
            //to completely avoid user generated situations where internalThread would be likely to never come to an end.
            //Especially, they disable a number of menu commands that could open probably persistent dialogs or toolbars,
            //which are not probably needed by users within Elexis. Moreover, they try to hide all toolbars and only
            //display the probably needed ones directly after loading the document (which is the earliest point in time
            //when it is beneficial, according to practical tests). But still, some dialogs can probably not be guaranteed
            //to never be required, and never persist, so its these remaining few against which the following timeout handler
            //shall finally help.
            //NOTE, IMPORTANT: It would also be a good precondition to "fixate" the toolbars within OpenOffice.
            //I just now remember this was a measure that I had originally taken on all our workstations, and it also appeared to help.
            //NOTE: Apparently - as demonstrated in the Mustermann letter with the table format dialog, the following beneficial thing happens:
            //If (!) the user detaches the table format dialog from the toolbars, that dialog becomes floating.
            //If he then closes the Briefe view, the floating dialog state is saved.
            //If he then re-loads the same Letter, the open floating dialog would stall the loader thread (for any reason whatsoever)
            //After some time, the limit below kicks in and the internalThread is destroyed.
            //The previously stalled OpenOffice, however, appears in the frame, and most probably...
            //my precautions shown somewhere else do immediately reconfigure the toolbars and cause the floating dialog to become docked!
            //When the user closes the window again, the new state is saved; and in future sessions, the dialog will not be floating any more
            //even when the same document is re-loaded. :-)
            //(Until the user decides to actively pull it out of the dock again, which should hardly ever happen.)
            //So only in very rare occasions, this very rude timout driven stall recovery needs to kick in,
            //and its benefits extend beyond resolving the acute situation. For a workaround, I think that's rather nice.
            //201202252154js
            if (cyclesWaitedForInternalThreadToComplete >= 0) {
                // 201210210818js: Counting up is held while the "do you want to destroyThread" dialog is visible.
                cyclesWaitedForInternalThreadToComplete = cyclesWaitedForInternalThreadToComplete + 1; //Each cycle currently sleeps for 500ms
            }

            System.out.println("LoadDocumentOperation: cyclesWaitedForInternalThreadToComplete: "
                    + cyclesWaitedForInternalThreadToComplete);

            //20130310js: Introduced in NOAText_jsl Version 1.4.8:
            //The timeout setting for the threaded watchdog is user configurable via the NOAText_jsl configuration dialog.
            //I don't want to read it from the preferenceStore directly, because we would have to do that in every cycle,
            //and it includes some string manipulation, needs 3 imports, and accessing a public static variable over there for the default value etc.
            //Instead, I have created a public static variable over there to provide the desired numeric value directly.
            int cyclesWatchdogMaximumAllowedHalfSecs = LocalOfficeApplicationPreferencesPage
                    .getTimeoutThreadedWatchdog();
            System.out.println("LoadDocumentOperation: Threaded watchdog timeout from NOAText_jsl preferences: "
                    + cyclesWatchdogMaximumAllowedHalfSecs);

            if (cyclesWatchdogMaximumAllowedHalfSecs == 0) {
                System.out.println(
                        "LoadDocumentOperation: Please note: Threaded watchdog = 0 means it has been disabled.");
            } else if (cyclesWaitedForInternalThreadToComplete > cyclesWatchdogMaximumAllowedHalfSecs) {
                cyclesWaitedForInternalThreadToComplete = -1; //Paranoia: Damit der nchste Thread.destroy() ggf. nicht schon in 0.5 Sek zuschlagen kann...

                //Version 1.4.5 hatte nach Ablauf des Watchdog automatisch ein internalThread.destroy() ausgelst.
                //Version 1.4.6 wollte dazu den Benutzer erst einmal fragen - aber wie ich gefunden habe:
                //   Der Dialog mit Frage nach Besttigung erschien keinesfalls vor Fertigstellen des Ladens eines Status in LibreOffice - Dauer 5 Minuten.
                //   In dieser Situation hatte ein vorzeitiges destroy() aber zu doc==null gefhrt, Fehlermeldungen, und nicht ersetzten Platzhaltern.
                //   Vielleicht anschliessend sogar zu nicht gespeichertem Dokument und gegebenenfalls spterer Instabilitt?
                //   Der Dialog erschien jedoch direkt nach Ablauf des Watchdog fr den Fall des wegen offener Toolbars etc. hngenden Ladeprozesses :-)
                //   Und tatschlich wurde in diesem Moment auch der Ladeprozess abgeschlossen. Ohne, dass noch ein destroy() ntig gewesen wre.
                //   Deshalb habe ich aus der MessageDialog.openConfirm() Variante nur noch eine ...openInformation() Variante gemacht.
                //   Hier wird auf das destroy() verzichtet, und der Anwendern nur noch informiert, dass NOAText die Verzgerung bemerkt hat,
                //   und woran sie liegen knnte.

                //Folgendes gehrt zur MessageDialog.openInformation() Variante:
                System.out.println(
                        "LoadDocumentOperation: MessageDialog.openInformation: Loading the document has taken too long.");
                System.out.println(
                        "LoadDocumentOperation: MessageDialog.openInformation: Holding watchdog timer counter while dialog is displayed.");

                //Folgendes gehrt zur MessageDialog.openConfirm() Variante:
                //System.out.println("LoadDocumentOperation: Operator question: Shall internalThread be destroyed?");
                //System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
                //System.out.println("WARNING: We shouldn't use internalthread.suspend, resume, stop, destroy... etc. for good reasons.");
                //System.out.println("WARNING: Please read the notes in the java online documentation for these methods! 201210210913js");
                //System.out.println("WARNING: Specifically, using internalThread.suspend() does NOT let the SWTHelper GUI Thread run anyway...");
                //System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");

                //201210210850js
                //SWTHelper.askYesNo() wrde das Asynchron machen wollen - und mit allem hier laufenden steckenbleiben.
                //Also nehme ich den Dialog-Code von dort direkt hierher. Fr Shell, MessageDialogs, Desk kommen oben drei imports hinzu. 
                //Desk.getDisplay();
                //Shell shell = Desk.getTopShell();
                //if (MessageDialog.openConfirm(shell, "Warning:",
                //internalThread.suspend();
                //if (SWTHelper.askYesNo("Warning:",

                //if (MessageDialog.openConfirm(null, "Warning:",            
                MessageDialog.openInformation(null, "Hinweis",
                        "NOAText: LoadDocumentOperation:\n\n" + "Das Laden des Dokuments dauert schon lnger als "
                                + cyclesWatchdogMaximumAllowedHalfSecs / 2 + " sec.\n"
                                + "Dies kann folgende Ursachen haben:\n\n"
                                + "(a) Das Starten des Office-Pakets und der Abruf des Dokuments aus der\n" + //<- in den Dialog zur Besttigung des watchdog:destroy() als Hinweis schreiben!
                                "      Datenbank dauern einfach so lang, ohne irgendeine Fehlfunktion.\n\n"
                                + "      Auf Wunsch kann ich den Grenzwert des Watchdog Timers erhhen.\n\n"
                                + "(b) LibreOffice kann zum ffnen von Dokumenten mit vielen Objekten\n" + //<- in den Dialog zur Besttigung des watchdog:destroy() als Hinweis schreiben!
                                "      mehrere Minuten bentigen - das ist keine Fehlfunktion in Elexis.\n\n" +
                                //"      Das Problem wird reproduzierbar sichtbar mit meiner experimentellen\n"+
                                //"      Vorlage zur Dokumentation einer krperlichen Untersuchung auf.\n\n"+
                                "      Die Wartezeit tritt auch auf, wenn man solche Dokumente ausserhalb\n"
                                + "      von Elexis ffnet. Im Task-Manager sieht man, dass soffice.bin\n"
                                + "      arbeitet, und der scheinbare Stillstand endet von selbst.\n\n" +
                                //"      Allerdings dauert dies z.B. auf einem i7 Q720 schon 5 Minuten.\n\n"+
                                "      Dies kann allerdings - je nach Dokument - mehrere Minuten dauern.\n\n"
                                + "      Falls Sie dieses Problem beobachten, sollten Sie bevorzugt\n"
                                + "      ApacheOpenOffice verwenden. Dieses ffnet solche Dokumente\n"
                                + "      offenbar ohne grssere Verzgerung.\n\n" +

                                //"      Selbst wenn man eine Unterbrechung auslst, lsst sich\n"+
                                //"      diese Wartezeit *nicht* verkrzen.\n\n"+
                                //"      In Folge der versuchten Unterbrechung wird aber das geladene\n"+
                                //"      Dokument fr Elexis nicht ansprechbar sein. Dann erscheinen\n"+
                                //"      mehrere Fehlermeldungen, und die Platzhalter im Dokument\n"+
                                //"      werden nicht mit Werten aus Elexis gefllt.\n\n"+

                                "(c) In OpenOffice/LibreOffice abgedockte Toolbars oder Dialoge\n"
                                + "      knnen das ffnen eines Dokuments aus Elexis heraus zum Stillstand\n"
                                + "      bringen. Auch beliebig langes Warten wrde hier *nicht* helfen.\n\n"
                                + "      Mit der Anzeige dieses Dialogs wird der Stillstand jedoch behoben.\n"
                                + "      Ausserdem werden in OpenOffice/LibreOffice abgedockte Toolbars\n"
                                + "      mglichst automatisch gedockt. Beim nchsten Aufruf eines Dokuments\n"
                                + "      knnte der Auslser des Fehlers also schon verschwunden sein.\n\n"
                                + "Falls Sie diese Fehlermeldung hufiger sehen, wre ich Ihnen fr\n"
                                + "Informationen zu den nheren Umstnden dankbar: joerg.sigle@jsigle.com\n\n"

                //Folgendes gehrt zru If MessageDialog.openInformation() Variante:
                );
                System.out.println(
                        "LoadDocumentOperation: MessageDialog.openInformation: Resetting watchdog timer counter.");
                cyclesWaitedForInternalThreadToComplete = 0; //let the watchdog timer start again

                //      //Folgendes gehrt zur If MessageDialog.openConfirm(...) Variante:
                //      //+"Mchten Sie eine fr Situation (a) gedachte Unterbrechung jetzt auslsen?")) {
                //
                //      //internalThread.resume();
                //      //201210210822 - If the user has decided to not destroy, and the process goes on for another watchdog maximum period, he will be asked again.
                //      System.out.println("LoadDocumentOperation: Operator response: Shall internalThread be destroyed? NO.");
                //      System.out.println("LoadDocumentOperation: WARNING: Restarting watchdog timer.");
                //      cyclesWaitedForInternalThreadToComplete=0;  //let the watchdog timer start again
                //      }
                //   else {
                //      //internalThread.resume();
                //      System.out.println("LoadDocumentOperation: Operator response: Shall internalThread be destroyed? YES.");
                //      System.out.println("LoadDocumentOperation: ERROR: internalThread timed out; will now be destroyed.");
                //      System.out.println("WARNING: This functionality should NOT be used except for debugging - see intenalThread.destroy() help .");
                //      System.out.println("WARNING: Destroying the internalThread is not guaranteed to return Elexis into a responsive state.");
                //      System.out.println("WARNING: Neither can we guarantee that the document that was about to be opened will appear correctly.");
                //      System.out.println("WARNING: That said, however, it DID succeed in some tests (4/5), and made the desired document");
                //      System.out.println("WARNING: appear with LibreOffice in its desired frame, and even the problematic floating dialog windows");
                //      System.out.println("WARNING: in addition to that - for either the table properties, or the externally opened F11 Formatvorlagen.");
                //      System.out.println("WARNING: 201202252133js");
                //      System.out.println("WARNING: For the example of the Status by JS and LibreOffice, however, the waiting will continue");
                //      System.out.println("WARNING: for almost 5 minutes on i7 720QM (!) with LibreOffice 3.6.2.2, and thereafter, doc==nul");
                //      System.out.println("WARNING: whereupon findOrReplace() will fail, placeholders will not be filled with data,");
                //      System.out.println("WARNING: and later on the document may not be saved (?), or the system will still stop after some occurences.");
                //      System.out.println("WARNING: 201210210807js");
                //      internalThread.destroy();   //this makes progressMonitor detect the end of the thread at least,
                //                           //but it is deprecated and very error prone. So this should NOT be used except for debugging.
                //      //  internalThread.stop();   //this does not stop progressMonitor from cycling on and on.
                //      
                //      //201210210822 - If we send a destroy while an attempt to open Status Vorlage w/ LibreOffice,
                //      //the thread will continue to require up to 5 mins anyway. Leaving cyclesWaited... at -1 would not show the dialog again,
                //      //putting it back to 0 will show it again. Well, it will probably not make things better if used, but keep the user informed at least.  
                //      cyclesWaitedForInternalThreadToComplete=0;   //let the watchdog timer start again
                //      Thread.sleep(500);         //Nach dem destroy des anderen Threads lasse ich hier noch eine halbe Sekunde Zeit.
                //      }
            }

        }

        System.out.println(
                "LoadDocumentOperation: run 3 TO DO / WARNING: REMOVED Thread.sleep(3000) here - but comment in code says that this might cause OOo 3.x to crash");
        // sleep here for a while otherwise OOo 3.x might crash
        //Thread.sleep(3000);
        System.out.println("LoadDocumentOperation: run 4 sleep ends");

        if (!isSubTask)
            progressMonitor.done();
        System.out.println("LoadDocumentOperation: run 5 done");
    }
    // ----------------------------------------------------------------------------

}