summaryrefslogtreecommitdiff
path: root/framework/qa/complex/framework
diff options
context:
space:
mode:
Diffstat (limited to 'framework/qa/complex/framework')
-rw-r--r--framework/qa/complex/framework/autosave/AutoSave.java454
-rw-r--r--framework/qa/complex/framework/autosave/ConfigHelper.java124
-rw-r--r--framework/qa/complex/framework/autosave/Protocol.java999
-rw-r--r--framework/qa/complex/framework/autosave/makefile.mk89
-rw-r--r--framework/qa/complex/framework/recovery/CrashThread.java80
-rw-r--r--framework/qa/complex/framework/recovery/KlickButtonThread.java57
-rw-r--r--framework/qa/complex/framework/recovery/RecoveryTest.java1012
-rw-r--r--framework/qa/complex/framework/recovery/RecoveryTools.java366
-rw-r--r--framework/qa/complex/framework/recovery/TimeoutThread.java41
-rwxr-xr-xframework/qa/complex/framework/recovery/makefile.mk103
10 files changed, 3325 insertions, 0 deletions
diff --git a/framework/qa/complex/framework/autosave/AutoSave.java b/framework/qa/complex/framework/autosave/AutoSave.java
new file mode 100644
index 000000000000..015d9771be59
--- /dev/null
+++ b/framework/qa/complex/framework/autosave/AutoSave.java
@@ -0,0 +1,454 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package complex.framework.autosave;
+
+import com.sun.star.frame.*;
+import com.sun.star.lang.*;
+import com.sun.star.util.*;
+import com.sun.star.beans.*;
+import com.sun.star.uno.*;
+import com.sun.star.sheet.*;
+import com.sun.star.table.*;
+
+import java.util.*;
+
+import complexlib.*;
+import helper.*;
+import util.*;
+
+//-----------------------------------------------
+/** @short Check some use cases of the AutoSave feature
+ */
+public class AutoSave extends ComplexTestCase
+{
+ //-------------------------------------------
+ class AutoSaveListener implements XStatusListener
+ {
+ private XDispatch m_xAutoSave;
+ private URL m_aRegistration;
+ private Protocol m_aLog;
+
+ public AutoSaveListener(XMultiServiceFactory xSMGR ,
+ XDispatch xAutoSave,
+ Protocol aLog )
+ {
+ m_aLog = aLog;
+ m_aLog.log(Protocol.TYPE_SCOPE_OPEN, "create listener for AutoSave notifications ...");
+
+ try
+ {
+ m_xAutoSave = xAutoSave;
+
+ XURLTransformer xParser = (XURLTransformer)UnoRuntime.queryInterface(
+ XURLTransformer.class,
+ xSMGR.createInstance("com.sun.star.util.URLTransformer"));
+ URL[] aURL = new URL[1];
+ aURL[0] = new URL();
+ aURL[0].Complete = "vnd.sun.star.autorecovery:/doAutoSave";
+ xParser.parseStrict(aURL);
+ m_aRegistration = aURL[0];
+
+ m_xAutoSave.addStatusListener(this, m_aRegistration);
+ m_aLog.log(Protocol.TYPE_INFO, "successfully registered as AutoSave listener.");
+ }
+ catch(Throwable ex)
+ {
+ m_aLog.log(ex);
+ }
+
+ m_aLog.log(Protocol.TYPE_SCOPE_CLOSE, "");
+ }
+
+ public void disableListener()
+ {
+ m_aLog.log(Protocol.TYPE_SCOPE_OPEN, "stop listening for AutoSave notifications ...");
+
+ XDispatch xAutoSave = null;
+ URL aRegURL = null;
+ synchronized (this)
+ {
+ xAutoSave = m_xAutoSave;
+ aRegURL = m_aRegistration;
+ }
+
+ try
+ {
+ if (
+ (xAutoSave != null) &&
+ (aRegURL != null)
+ )
+ xAutoSave.removeStatusListener(this, aRegURL);
+ }
+ catch(Throwable ex)
+ {
+ m_aLog.log(ex);
+ }
+
+ m_aLog.log(Protocol.TYPE_SCOPE_CLOSE, "");
+ }
+
+ public void statusChanged(FeatureStateEvent aEvent)
+ {
+ m_aLog.log(Protocol.TYPE_SCOPE_OPEN, "statusChanged() called from AutoSave ...");
+
+ m_aLog.log("FeatureURL = \""+aEvent.FeatureURL.Complete+"\"" );
+ m_aLog.log("FeatureDescriptor = \""+aEvent.FeatureDescriptor+"\"" );
+ m_aLog.log("IsEnabled = \""+aEvent.IsEnabled+"\"" );
+ m_aLog.log("Requery = \""+aEvent.Requery+"\"" );
+ m_aLog.log("State:" );
+ m_aLog.log(aEvent.State );
+
+ m_aLog.log(Protocol.TYPE_SCOPE_CLOSE, "");
+ }
+
+ public void disposing(com.sun.star.lang.EventObject aEvent)
+ {
+ m_aLog.log(Protocol.TYPE_INFO, "disposing() called from AutoSave.");
+ synchronized(this)
+ {
+ m_xAutoSave = null;
+ m_aRegistration = null;
+ }
+ }
+ }
+
+ //-------------------------------------------
+ // some const
+
+ //-------------------------------------------
+ // member
+
+ private Protocol m_aLog;
+
+ /** points to the global uno service manager. */
+ private XMultiServiceFactory m_xSMGR = null;
+
+ private SOfficeFactory m_aSOF;
+
+ /** can be used to trigger/enable/disable the AutoSave feature. */
+ private XDispatch m_xAutoSave = null;
+
+ /** a test document, which needs some time for saving to simulate concurrent
+ * save operations. */
+ private XStorable m_xTestDoc = null;
+
+ private XURLTransformer m_xURLParser = null;
+
+ //-------------------------------------------
+ // test environment
+
+ //-------------------------------------------
+ /** @short A function to tell the framework,
+ which test functions are available.
+
+ @return All test methods.
+ @todo Think about selection of tests from outside ...
+ */
+ public String[] getTestMethodNames()
+ {
+ return new String[]
+ {
+ "checkConcurrentAutoSaveToNormalUISave",
+ };
+ }
+
+ //-------------------------------------------
+ /** @short Create the environment for following tests.
+
+ @descr create an empty test frame, where we can load
+ different components inside.
+ */
+ public void before()
+ {
+ m_aLog = new Protocol(Protocol.MODE_HTML | Protocol.MODE_STDOUT, Protocol.FILTER_NONE, utils.getUsersTempDir() + "/complex_log_ascii_01.html");
+
+ try
+ {
+ // get uno service manager from global test environment
+ m_xSMGR = (XMultiServiceFactory)param.getMSF();
+
+ // get another helper to e.g. create test documents
+ m_aSOF = SOfficeFactory.getFactory(m_xSMGR);
+
+ // create AutoSave instance
+ m_xAutoSave = (XDispatch)UnoRuntime.queryInterface(
+ XDispatch.class,
+ m_xSMGR.createInstance("com.sun.star.comp.framework.AutoRecovery"));
+
+ // prepare AutoSave
+ // make sure it will be started every 1 min
+ ConfigHelper aConfig = new ConfigHelper(m_xSMGR, "org.openoffice.Office.Recovery", false);
+ aConfig.writeRelativeKey("AutoSave", "Enabled" , Boolean.TRUE );
+ aConfig.writeRelativeKey("AutoSave", "TimeIntervall", new Integer(1)); // 1 min
+ aConfig.flush();
+ aConfig = null;
+
+ // is needed to parse dispatch commands
+ m_xURLParser = (XURLTransformer)UnoRuntime.queryInterface(
+ XURLTransformer.class,
+ m_xSMGR.createInstance("com.sun.star.util.URLTransformer"));
+
+ }
+ catch(java.lang.Throwable ex)
+ {
+ m_aLog.log(ex);
+ failed("Couldn't create test environment");
+ }
+ }
+
+ //-------------------------------------------
+ /** @short close the environment.
+ */
+ public void after()
+ {
+ // ???
+ }
+
+ //-------------------------------------------
+ // create a calc document with content, which needs some time for saving
+ private XInterface createBigCalcDoc()
+ {
+ m_aLog.log(Protocol.TYPE_SCOPE_OPEN, "createBigCalcDoc() started ...");
+ try
+ {
+ m_aLog.log("Create empty calc document for testing.");
+ XSpreadsheetDocument xSheetDoc = m_aSOF.createCalcDoc("_default");
+ m_aLog.log("Retrieve first sheet from calc document.");
+ XSpreadsheets xSheets = xSheetDoc.getSheets();
+ XSpreadsheet xSheet = (XSpreadsheet)AnyConverter.toObject(
+ new Type(XSpreadsheet.class),
+ xSheets.getByName(
+ xSheets.getElementNames()[0]));
+ m_aLog.log("Fill two cells with value and formula.");
+ xSheet.getCellByPosition(0, 0).setValue(1);
+ xSheet.getCellByPosition(0, 1).setFormula("=a1+1");
+ m_aLog.log("Retrieve big range.");
+ XCellRange xRange = xSheet.getCellRangeByName("A1:Z9999");
+ XCellSeries xSeries = (XCellSeries)UnoRuntime.queryInterface(
+ XCellSeries.class,
+ xRange);
+ m_aLog.log("Duplicate cells from top to bottom inside range.");
+ xSeries.fillAuto(FillDirection.TO_BOTTOM, 2);
+ m_aLog.log("Duplicate cells from left to right inside range.");
+ xSeries.fillAuto(FillDirection.TO_RIGHT , 1);
+
+ m_aLog.log(Protocol.TYPE_SCOPE_CLOSE | Protocol.TYPE_OK, "createBigCalcDoc() finished.");
+ return xSheetDoc;
+ }
+ catch(Throwable ex)
+ {
+ m_aLog.log(ex);
+ }
+
+ m_aLog.log(Protocol.TYPE_SCOPE_CLOSE, "createBigCalcDoc() finished.");
+ return null;
+ }
+
+ //-------------------------------------------
+ private void saveDoc(XInterface xDoc,
+ String sURL)
+ {
+ m_aLog.log(Protocol.TYPE_SCOPE_OPEN, "saveDoc('"+sURL+"') started ...");
+ try
+ {
+ URL[] aURL = new URL[1];
+ aURL[0] = new URL();
+ aURL[0].Complete = ".uno:SaveAs";
+ m_xURLParser.parseStrict(aURL);
+
+ XModel xModel = (XModel)UnoRuntime.queryInterface(
+ XModel.class,
+ xDoc);
+ XDispatchProvider xProvider = (XDispatchProvider)UnoRuntime.queryInterface(
+ XDispatchProvider.class,
+ xModel.getCurrentController());
+ XDispatch xDispatch = xProvider.queryDispatch(aURL[0], "_self", 0);
+
+ PropertyValue[] lArgs = new PropertyValue[3];
+ lArgs[0] = new PropertyValue();
+ lArgs[0].Name = "URL";
+ lArgs[0].Value = sURL;
+ lArgs[1] = new PropertyValue();
+ lArgs[1].Name = "Overwrite";
+ lArgs[1].Value = Boolean.TRUE;
+ lArgs[2] = new PropertyValue();
+ lArgs[2].Name = "StoreTo";
+ lArgs[2].Value = Boolean.TRUE;
+
+ xDispatch.dispatch(aURL[0], lArgs);
+
+ m_aLog.log(Protocol.TYPE_OK, "saveDoc('"+sURL+"') = OK.");
+ }
+/*
+ catch(com.sun.star.io.IOException exIO)
+ {
+ m_aLog.log(Protocol.TYPE_WARNING , "got IOException on calling doc.store()." );
+ m_aLog.log(Protocol.TYPE_WARNING_INFO, "Please check the reason for that more in detail." );
+ m_aLog.log(Protocol.TYPE_WARNING_INFO, "A message like \"Concurrent save requests are not allowed.\" was intended and doesnt show an error!");
+ m_aLog.log(Protocol.TYPE_WARNING_INFO, "Message of the original exception:" );
+ m_aLog.log(Protocol.TYPE_WARNING_INFO, exIO.getMessage());
+ }
+*/
+ catch(Throwable ex)
+ {
+ m_aLog.log(ex);
+ }
+ m_aLog.log(Protocol.TYPE_SCOPE_CLOSE, "saveDoc('"+sURL+"') finished.");
+ }
+
+ //-------------------------------------------
+ private void closeDoc(XInterface xDoc)
+ {
+ m_aLog.log(Protocol.TYPE_SCOPE_OPEN, "closeDoc() started ...");
+
+ try
+ {
+ Random aRandom = new Random();
+ int nRetry = 5;
+ while(nRetry>0)
+ {
+ try
+ {
+ XCloseable xClose = (XCloseable)UnoRuntime.queryInterface(
+ XCloseable.class,
+ xDoc);
+ if (xClose != null)
+ {
+ xClose.close(false);
+ m_aLog.log(Protocol.TYPE_OK, "closeDoc() = OK.");
+ nRetry = 0;
+ }
+ else
+ m_aLog.log(Protocol.TYPE_ERROR, "closeDoc() = ERROR. Doc doesnt provide needed interface!");
+ }
+ catch(com.sun.star.util.CloseVetoException exVeto)
+ {
+ m_aLog.log(Protocol.TYPE_WARNING , "got CloseVetoException on calling doc.close()." );
+ m_aLog.log(Protocol.TYPE_WARNING_INFO, "Please check the reason for that more in detail." );
+ m_aLog.log(Protocol.TYPE_WARNING_INFO, "A message like \"Cant close while saving.\" was intended and doesnt show an error!");
+ m_aLog.log(Protocol.TYPE_WARNING_INFO, exVeto.getMessage());
+ }
+
+ if (nRetry > 0)
+ {
+ --nRetry;
+ long nWait = (long)aRandom.nextInt(30000); // 30 sec.
+ try
+ {
+ m_aLog.log(Protocol.TYPE_INFO, "sleep for "+nWait+" ms");
+ synchronized(this)
+ {
+ wait(nWait);
+ }
+ }
+ catch(Throwable ex)
+ {
+ m_aLog.log(Protocol.TYPE_WARNING , "got exception for wait() !?");
+ m_aLog.log(Protocol.TYPE_WARNING_INFO, ex.getMessage());
+ }
+ }
+ }
+ }
+ catch(Throwable ex)
+ {
+ m_aLog.log(ex);
+ }
+
+ m_aLog.log(Protocol.TYPE_SCOPE_CLOSE, "closeDoc() finished.");
+ }
+
+ class DocThread extends Thread
+ {
+ DocThread()
+ {}
+
+ public void run()
+ {
+ impl_checkConcurrentAutoSaveToNormalUISave();
+ }
+ }
+
+ //-------------------------------------------
+ /** @short check concurrent save requests to the same document
+ * at the same time.
+ *
+ * @descr First we simulate an UI save by dispatching the right URL
+ * to the document and at the same time we try to trigger an AutoSave
+ * from another thread. So these operations should be started at the same time.
+ * It should not crash. The AutoSave request must be postphoned.
+ */
+ public void checkConcurrentAutoSaveToNormalUISave()
+ {
+ m_aLog.log(Protocol.TYPE_TESTMARK , "AutoSave");
+ m_aLog.log(Protocol.TYPE_SCOPE_OPEN, "checkConcurrentAutoSaveToNormalUISave()");
+
+ AutoSaveListener xListener = new AutoSaveListener(m_xSMGR, m_xAutoSave, m_aLog);
+
+ try
+ {
+ DocThread aThread = new DocThread();
+ aThread.start();
+ aThread.join();
+ }
+ catch(Throwable ex)
+ {}
+
+ xListener.disableListener();
+
+ m_aLog.log(Protocol.TYPE_SCOPE_CLOSE, "checkConcurrentAutoSaveToNormalUISave()");
+ m_aLog.logStatistics();
+ }
+
+ public void impl_checkConcurrentAutoSaveToNormalUISave()
+ {
+ Random aRandom = new Random();
+
+ int i = 0;
+ int c = 5;
+ for (i=0; i<c; ++i)
+ {
+ XInterface xDoc = createBigCalcDoc();
+ try
+ {
+ long nWait = (long)aRandom.nextInt(120000);
+ m_aLog.log(Protocol.TYPE_INFO, "sleep for "+nWait+" ms");
+ synchronized(this)
+ {
+ wait(nWait);
+ }
+ }
+ catch(Throwable ex)
+ {
+ m_aLog.log(Protocol.TYPE_WARNING , "got exception for wait() !?");
+ m_aLog.log(Protocol.TYPE_WARNING_INFO, ex.getMessage());
+ }
+ saveDoc(xDoc, utils.getOfficeTemp(m_xSMGR) + "/test_calc.ods");
+ closeDoc(xDoc);
+ }
+ }
+}
diff --git a/framework/qa/complex/framework/autosave/ConfigHelper.java b/framework/qa/complex/framework/autosave/ConfigHelper.java
new file mode 100644
index 000000000000..3bc4683f4fb5
--- /dev/null
+++ b/framework/qa/complex/framework/autosave/ConfigHelper.java
@@ -0,0 +1,124 @@
+package complex.framework.autosave;
+
+import java.lang.*;
+import com.sun.star.uno.*;
+import com.sun.star.lang.*;
+import com.sun.star.container.*;
+import com.sun.star.beans.*;
+import com.sun.star.util.*;
+
+class ConfigHelper
+{
+ private XMultiServiceFactory m_xSMGR = null;
+ private XHierarchicalNameAccess m_xConfig = null;
+
+ //-----------------------------------------------
+ public ConfigHelper(XMultiServiceFactory xSMGR ,
+ String sConfigPath ,
+ boolean bReadOnly )
+ throws com.sun.star.uno.Exception
+ {
+ m_xSMGR = xSMGR;
+
+ XMultiServiceFactory xConfigRoot = (XMultiServiceFactory)UnoRuntime.queryInterface(
+ XMultiServiceFactory.class,
+ m_xSMGR.createInstance("com.sun.star.configuration.ConfigurationProvider"));
+
+ PropertyValue[] lParams = new PropertyValue[1];
+ lParams[0] = new PropertyValue();
+ lParams[0].Name = "nodepath";
+ lParams[0].Value = sConfigPath;
+
+ Object aConfig;
+ if (bReadOnly)
+ aConfig = xConfigRoot.createInstanceWithArguments(
+ "com.sun.star.configuration.ConfigurationAccess",
+ lParams);
+ else
+ aConfig = xConfigRoot.createInstanceWithArguments(
+ "com.sun.star.configuration.ConfigurationUpdateAccess",
+ lParams);
+
+ m_xConfig = (XHierarchicalNameAccess)UnoRuntime.queryInterface(
+ XHierarchicalNameAccess.class,
+ aConfig);
+
+ if (m_xConfig == null)
+ throw new com.sun.star.uno.Exception("Could not open configuration \""+sConfigPath+"\"");
+ }
+
+ //-----------------------------------------------
+ public Object readRelativeKey(String sRelPath,
+ String sKey )
+ throws com.sun.star.container.NoSuchElementException
+ {
+ try
+ {
+ XPropertySet xPath = (XPropertySet)UnoRuntime.queryInterface(
+ XPropertySet.class,
+ m_xConfig.getByHierarchicalName(sRelPath));
+ return xPath.getPropertyValue(sKey);
+ }
+ catch(com.sun.star.uno.Exception ex)
+ {
+ throw new com.sun.star.container.NoSuchElementException(ex.getMessage());
+ }
+ }
+
+ //-----------------------------------------------
+ public void writeRelativeKey(String sRelPath,
+ String sKey ,
+ Object aValue )
+ throws com.sun.star.container.NoSuchElementException
+ {
+ try
+ {
+ XPropertySet xPath = (XPropertySet)UnoRuntime.queryInterface(
+ XPropertySet.class,
+ m_xConfig.getByHierarchicalName(sRelPath));
+ xPath.setPropertyValue(sKey, aValue);
+ }
+ catch(com.sun.star.uno.Exception ex)
+ {
+ throw new com.sun.star.container.NoSuchElementException(ex.getMessage());
+ }
+ }
+
+ //-----------------------------------------------
+ public void flush()
+ {
+ try
+ {
+ XChangesBatch xBatch = (XChangesBatch)UnoRuntime.queryInterface(
+ XChangesBatch.class,
+ m_xConfig);
+ xBatch.commitChanges();
+ }
+ catch(com.sun.star.uno.Exception ex)
+ {}
+ }
+
+ //-----------------------------------------------
+ public static Object readDirectKey(XMultiServiceFactory xSMGR ,
+ String sConfigFile,
+ String sRelPath ,
+ String sKey )
+ throws com.sun.star.uno.Exception
+ {
+ ConfigHelper aConfig = new ConfigHelper(xSMGR, sConfigFile, true);
+ return aConfig.readRelativeKey(sRelPath, sKey);
+ }
+
+ //-----------------------------------------------
+ public static void writeDirectKey(XMultiServiceFactory xSMGR ,
+ String sConfigFile,
+ String sRelPath ,
+ String sKey ,
+ Object aValue )
+ throws com.sun.star.uno.Exception
+ {
+ ConfigHelper aConfig = new ConfigHelper(xSMGR, sConfigFile, false);
+ aConfig.writeRelativeKey(sRelPath, sKey, aValue);
+ aConfig.flush();
+ }
+}
diff --git a/framework/qa/complex/framework/autosave/Protocol.java b/framework/qa/complex/framework/autosave/Protocol.java
new file mode 100644
index 000000000000..11f6c4eeeff3
--- /dev/null
+++ b/framework/qa/complex/framework/autosave/Protocol.java
@@ -0,0 +1,999 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package complex.framework.autosave;
+
+// __________ Imports __________
+
+// structs, const, ...
+import com.sun.star.beans.PropertyValue;
+import com.sun.star.bridge.XUnoUrlResolver;
+
+// exceptions
+import com.sun.star.container.NoSuchElementException;
+import com.sun.star.uno.Exception;
+import com.sun.star.uno.RuntimeException;
+import java.io.IOException;
+import java.lang.InterruptedException;
+import java.net.ConnectException;
+
+// interfaces
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.uno.Any;
+
+// helper
+import com.sun.star.uno.IBridge;
+import com.sun.star.uno.UnoRuntime;
+
+// others
+import javax.swing.*;
+import javax.swing.border.*;
+import java.awt.*;
+import java.lang.*;
+import java.io.*;
+import java.util.*;
+import java.sql.*;
+
+// __________ Implementation __________
+
+/**
+ * Implements a log mechanism to create a protocol of all steps of e.g. an api test
+ * It provides the possibility to write the logged meesages to a file and/or
+ * to stdout/stderr (if neccessary at the same time!).
+ *
+ * TODO
+ * - implement filter, which e.g. supress showing of INFO data
+ */
+public class Protocol extends JComponent
+{
+ // ____________________
+ /**
+ * Note: Following values can be combined - they are interpreted as flags.
+ *
+ * @const MODE_STDOUT messages are logged to stdout
+ * @const MODE_STDERR messages are logged to stderr
+ * @const MODE_ASCII messages are logged to an ascii file
+ * @const MODE_HTML messages are logged to a html file
+ *
+ * @const TYPE_SCOPE_OPEN open, mark or count a new scope for following log statements
+ * @const TYPE_SCOPE_CLOSE close, mark or count the current scope
+ * @const TYPE_TESTMARK it marks the beginning of a (sub)test, can be used for statistic purposes
+ * @const TYPE_OK this protocol line is marked as a OK message
+ * @const TYPE_ERROR this protocol line is marked as an error
+ * @const TYPE_WARNING this protocol line is marked as a warning
+ * @const TYPE_INFO this protocol line represent some debug data for analyzing
+ */
+ public static final int MODE_STDOUT = 1;
+ public static final int MODE_STDERR = 2;
+ public static final int MODE_ASCII = 4;
+ public static final int MODE_HTML = 8;
+
+ public static final int TYPE_OK = 1;
+ public static final int TYPE_ERROR = 2;
+ public static final int TYPE_WARNING = 4;
+ public static final int TYPE_INFO = 8;
+ public static final int TYPE_SCOPE_OPEN = 16;
+ public static final int TYPE_SCOPE_CLOSE = 32;
+ public static final int TYPE_TESTMARK = 64;
+ public static final int TYPE_ERROR_INFO = 128;
+ public static final int TYPE_WARNING_INFO = 256;
+ public static final int TYPE_STATISTIC = 512;
+ public static final int TYPE_LINK = 1024;
+
+ public static final int FILTER_NONE = 0;
+ public static final int FILTER_OK = TYPE_OK;
+ public static final int FILTER_ERROR = TYPE_ERROR;
+ public static final int FILTER_WARNING = TYPE_WARNING;
+ public static final int FILTER_INFO = TYPE_INFO;
+ public static final int FILTER_SCOPES = TYPE_SCOPE_OPEN | TYPE_SCOPE_CLOSE;
+ public static final int FILTER_TESTMARK = TYPE_TESTMARK;
+ public static final int FILTER_ERROR_INFO = TYPE_ERROR_INFO;
+ public static final int FILTER_WARNING_INFO = TYPE_WARNING_INFO;
+ public static final int FILTER_STATISTIC = TYPE_STATISTIC;
+ public static final int FILTER_LINK = TYPE_LINK;
+
+ // ____________________
+ /**
+ */
+ private static final int MARK_DIFF = 5;
+
+ private static final String BGCOLOR_LINECOL = "#95CC77";
+ private static final String FGCOLOR_LINECOL_NORMAL = "#ffffbd";
+ private static final String FGCOLOR_LINECOL_MARKED = "#000088";
+
+ private static final String BGCOLOR_STANDARD = "#ffffff";
+ private static final String FGCOLOR_STANDARD = "#000000";
+
+ private static final String BGCOLOR_SCOPE = "#eeeeee";
+ private static final String FGCOLOR_SCOPE = "#000000";
+
+ private static final String BGCOLOR_TIMESTAMP = "#e0e0e0";
+ private static final String FGCOLOR_TIMESTAMP = "#000000";
+
+ private static final String BGCOLOR_TESTMARK = "#0000ff";
+ private static final String FGCOLOR_TESTMARK = "#ffffff";
+
+ private static final String BGCOLOR_OK = "#88dd88";
+ private static final String FGCOLOR_OK = "#ffffff";
+
+ private static final String BGCOLOR_WARNING = "#ffff00";
+ private static final String FGCOLOR_WARNING = "#000000";
+
+ private static final String BGCOLOR_WARNING_INFO = "#ffffcc";
+ private static final String FGCOLOR_WARNING_INFO = "#000000";
+
+ private static final String BGCOLOR_ERROR = "#ff0000";
+ private static final String FGCOLOR_ERROR = "#ffff00";
+
+ private static final String BGCOLOR_ERROR_INFO = "#ffbbbb";
+ private static final String FGCOLOR_ERROR_INFO = "#000000";
+
+ private static final String BGCOLOR_INFO = "#eeeeee";
+ private static final String FGCOLOR_INFO = "#000000";
+
+ private static final String BGCOLOR_STATISTIC = "#0000ff";
+ private static final String FGCOLOR_STATISTIC = "#ffffff";
+
+ private static final String BGCOLOR_LINK = BGCOLOR_INFO;
+ private static final String FGCOLOR_LINK = FGCOLOR_INFO;
+
+ // ____________________
+ /**
+ * @member m_nMode the mode, in which this protocol object runs
+ * @member m_nFilter can be used to filter log messages by type
+ * @member m_sFileName we need it to open the log file on demand (if nMode require such log file)
+ * @member m_nLine used as line number for the protocol
+ * @member m_nScope used to format scopes
+ * @member m_nErrors count errors in protocol
+ * @member m_nWarnings count warnings in protocol
+ * @member m_nTestMarks count test marker in protocol
+ */
+ private int m_nMode ;
+ private int m_nFilter ;
+ private String m_sFileName ;
+ private long m_nLine ;
+ private long m_nScope ;
+ private long m_nErrors ;
+ private long m_nWarnings ;
+ private long m_nTestMarks;
+ private Timestamp m_aStartTime;
+ private Timestamp m_aEndTime ;
+
+ // ____________________
+ /**
+ * special helper class to represent one line of a protocol.
+ * Such line can be specified as a special one (ERROR, WARNING ...).
+ * That makes it possible to analyze the whole protocol using tools.
+ */
+ class ProtocolLine
+ {
+ /// the line number of this protocol line (size of the vector of all protocol lines cn be used to count such lines!)
+ private long m_nLine;
+ /// deepness of the current scope
+ private long m_nScope;
+ /// mark line as an error, warning, data entry ... (see const definitions before)
+ private int m_nType;
+ /// of course, we have to know the logged message too :-)
+ private String m_sMessage;
+ /// and it can be usefull to know the current time, when this line was created
+ private Timestamp m_aStamp;
+
+ /** ctor for fast initializing of such line */
+ public ProtocolLine( long nLine ,
+ long nScope ,
+ int nType ,
+ String sMessage )
+ {
+ m_aStamp = new Timestamp(System.currentTimeMillis());
+ m_nLine = nLine ;
+ m_nScope = nScope ;
+ m_nType = nType ;
+ m_sMessage = sMessage;
+ }
+
+ /** format this line as an ascii string for writing log files */
+ public synchronized String toString()
+ {
+ StringBuffer sLine = new StringBuffer(1000);
+
+ // insert line number
+ // Use right bound notation and format 6 digits!
+ sLine.append("[" );
+ if (m_nLine<10)
+ sLine.append(" ");
+ else
+ if (m_nLine<100)
+ sLine.append(" ");
+ else
+ if (m_nLine<1000)
+ sLine.append(" ");
+ else
+ if (m_nLine<10000)
+ sLine.append(" ");
+ else
+ if (m_nLine<100000)
+ sLine.append(" ");
+ sLine.append(m_nLine);
+ sLine.append("] " );
+
+ // add time stamp
+ // close with a "TAB" ... because some time stamps are not normalized to
+ // a well defined string length .-)
+ sLine.append(m_aStamp.toString()+" \t");
+
+ // add special line type
+ if ((m_nType & TYPE_OK) == TYPE_OK)
+ sLine.append(" OK ");
+ else
+ if ((m_nType & TYPE_ERROR) == TYPE_ERROR)
+ sLine.append(" ERROR ");
+ else
+ if ((m_nType & TYPE_ERROR_INFO) == TYPE_ERROR_INFO)
+ sLine.append(" ERROR INFO ");
+ else
+ if ((m_nType & TYPE_WARNING) == TYPE_WARNING)
+ sLine.append(" WARNING ");
+ else
+ if ((m_nType & TYPE_WARNING_INFO) == TYPE_WARNING_INFO)
+ sLine.append(" WARNING INFO ");
+ else
+ if ((m_nType & TYPE_INFO) == TYPE_INFO)
+ sLine.append(" INFO ");
+ else
+ if ((m_nType & TYPE_TESTMARK) == TYPE_TESTMARK)
+ sLine.append(" TEST ");
+ else
+ if ((m_nType & TYPE_LINK) == TYPE_LINK)
+ sLine.append(" LINK ");
+ else
+ if ((m_nType & TYPE_STATISTIC) == TYPE_STATISTIC)
+ sLine.append(" STATISTIC ");
+ else
+ if (
+ ((m_nType & TYPE_SCOPE_OPEN ) == TYPE_SCOPE_OPEN ) ||
+ ((m_nType & TYPE_SCOPE_CLOSE) == TYPE_SCOPE_CLOSE)
+ )
+ sLine.append(" SCOPE ");
+ else
+ sLine.append(" ");
+
+ // add scope information
+ for (int s=0; s<m_nScope; ++s)
+ sLine.append(" ");
+
+ if ((m_nType & TYPE_SCOPE_OPEN) == TYPE_SCOPE_OPEN)
+ sLine.append(" { ");
+ else
+ if ((m_nType & TYPE_SCOPE_CLOSE) == TYPE_SCOPE_CLOSE)
+ sLine.append(" } ");
+ else
+ sLine.append(" ");
+
+ // add message
+ sLine.append(m_sMessage);
+ sLine.append("\n" );
+
+ return sLine.toString();
+ }
+
+ /**
+ * format this line as a string for writing log files
+ * using the html format
+ */
+ public synchronized String toHTML()
+ {
+ StringBuffer sLine = new StringBuffer(1000);
+ sLine.append("<tr>");
+
+ // insert line number
+ if (m_nLine % MARK_DIFF == 0)
+ impl_generateColoredHTMLCell(sLine, new Long(m_nLine).toString(), BGCOLOR_LINECOL, FGCOLOR_LINECOL_MARKED, true);
+ else
+ impl_generateColoredHTMLCell(sLine, new Long(m_nLine).toString(), BGCOLOR_LINECOL, FGCOLOR_LINECOL_NORMAL, false);
+
+ // add time stamp
+ impl_generateColoredHTMLCell(sLine, m_aStamp.toString()+" ", BGCOLOR_TIMESTAMP, FGCOLOR_TIMESTAMP, false);
+
+ // add log type info
+ boolean bTypeCellFilled = false;
+ if ((m_nType & TYPE_ERROR_INFO) == TYPE_ERROR_INFO)
+ {
+ impl_generateColoredHTMLCell(sLine, "ERROR INFO", BGCOLOR_ERROR_INFO, FGCOLOR_ERROR_INFO, false);
+ bTypeCellFilled = true;
+ }
+ else
+ if ((m_nType & TYPE_ERROR) == TYPE_ERROR)
+ {
+ impl_generateColoredHTMLCell(sLine, "ERROR", BGCOLOR_ERROR, FGCOLOR_ERROR, true);
+ bTypeCellFilled = true;
+ }
+ else
+ if ((m_nType & TYPE_WARNING_INFO) == TYPE_WARNING_INFO)
+ {
+ impl_generateColoredHTMLCell(sLine, "WARNING INFO", BGCOLOR_WARNING_INFO, FGCOLOR_WARNING_INFO, false);
+ bTypeCellFilled = true;
+ }
+ else
+ if ((m_nType & TYPE_WARNING) == TYPE_WARNING)
+ {
+ impl_generateColoredHTMLCell(sLine, "WARNING", BGCOLOR_WARNING, FGCOLOR_WARNING, true);
+ bTypeCellFilled = true;
+ }
+ else
+ if ((m_nType & TYPE_OK) == TYPE_OK)
+ {
+ impl_generateColoredHTMLCell(sLine, "OK", BGCOLOR_OK, FGCOLOR_OK, true);
+ bTypeCellFilled = true;
+ }
+ else
+ if ((m_nType & TYPE_INFO) == TYPE_INFO)
+ {
+ impl_generateColoredHTMLCell(sLine, "INFO", BGCOLOR_INFO, FGCOLOR_INFO, false);
+ bTypeCellFilled = true;
+ }
+ else
+ if ((m_nType & TYPE_TESTMARK) == TYPE_TESTMARK)
+ {
+ impl_generateColoredHTMLCell(sLine, "TEST", BGCOLOR_TESTMARK, FGCOLOR_TESTMARK, true);
+ bTypeCellFilled = true;
+ }
+ else
+ if ((m_nType & TYPE_STATISTIC) == TYPE_STATISTIC)
+ {
+ impl_generateColoredHTMLCell(sLine, "STATISTIC", BGCOLOR_STATISTIC, FGCOLOR_STATISTIC, false);
+ bTypeCellFilled = true;
+ }
+ else
+ if ((m_nType & TYPE_LINK) == TYPE_LINK)
+ {
+ impl_generateColoredHTMLCell(sLine, "LINK", BGCOLOR_LINK, FGCOLOR_LINK, false);
+ bTypeCellFilled = true;
+ }
+ else
+ if (
+ ((m_nType & TYPE_SCOPE_OPEN ) == TYPE_SCOPE_OPEN ) ||
+ ((m_nType & TYPE_SCOPE_CLOSE) == TYPE_SCOPE_CLOSE)
+ )
+ {
+ impl_generateColoredHTMLCell(sLine, "SCOPE", BGCOLOR_SCOPE, FGCOLOR_SCOPE, false);
+ bTypeCellFilled = true;
+ }
+
+ // if no tyope information was added to the current coloum, we must
+ // write any content into this cell. Otherwise some browser
+ // shows a strange layout!
+ if (! bTypeCellFilled)
+ impl_generateColoredHTMLCell(sLine, " ", BGCOLOR_STANDARD, FGCOLOR_STANDARD, false);
+
+ // add scope information
+ sLine.append("<td>");
+ for (int s=0; s<m_nScope; ++s)
+ sLine.append("&nbsp;&nbsp;&nbsp;");
+ String sColor = "#000000";
+ if ((m_nScope % 2) == 0)
+ sColor = "#808080";
+ if ((m_nType & TYPE_SCOPE_OPEN) == TYPE_SCOPE_OPEN)
+ sLine.append("<font color=\""+sColor+"\">{ "+m_nScope+"</font>");
+ else
+ if ((m_nType & TYPE_SCOPE_CLOSE) == TYPE_SCOPE_CLOSE)
+ sLine.append("<font color=\""+sColor+"\">"+m_nScope+" }</font>");
+ sLine.append("</td>\n");
+
+ // add message
+ sLine.append("<td>" );
+ sLine.append(m_sMessage);
+ sLine.append("</td>\n" );
+
+ sLine.append("</tr>\n" );
+
+ return sLine.toString();
+ }
+
+ /** detect, if this line object represent an error */
+ public synchronized boolean isError()
+ {
+ return (
+ ((m_nType & TYPE_ERROR) == TYPE_ERROR) &&
+ ((m_nType & TYPE_INFO ) != TYPE_INFO )
+ );
+ }
+
+ /** detect, if this line object represent a warning */
+ public synchronized boolean isWarning()
+ {
+ return (
+ ((m_nType & TYPE_WARNING) == TYPE_WARNING) &&
+ ((m_nType & TYPE_INFO ) != TYPE_INFO )
+ );
+ }
+
+ /** detect, if this line object represent a marked position */
+ public synchronized boolean isTestMark()
+ {
+ return ((m_nType & TYPE_TESTMARK) == TYPE_TESTMARK);
+ }
+
+ /**
+ * create a colored table cell formated as HTML.
+ *
+ * @param sCell
+ * an outside string buffer, which can be
+ * used to generate the
+ * needed HTML code there.
+ *
+ * @param sContent
+ * the text content of this cell.
+ *
+ * @param sBGColor
+ * a string, which represent the background color
+ * coded in HTML.
+ *
+ * @param sFGColor
+ * a string, which represent the foreground color
+ * coded in HTML.
+ *
+ * @param bBold
+ * enable/disable bold state for the text content.
+ */
+ private void impl_generateColoredHTMLCell(StringBuffer sCell ,
+ String sContent,
+ String sBGColor,
+ String sFGColor,
+ boolean bBold )
+ {
+ sCell.append("<td bgcolor=\""+sBGColor+"\">");
+ sCell.append("<font color=\""+sFGColor+"\">");
+ if (bBold)
+ sCell.append("<b>");
+ sCell.append(sContent);
+ if (bBold)
+ sCell.append("</b>");
+ sCell.append("</font></td>\n");
+ }
+ }
+
+ // ____________________
+ /**
+ * ctor
+ * It creates a new instance of this class and innitialize it in the right mode.
+ *
+ * @param nMode
+ * specify how the log should be generated.
+ *
+ * @param nFilter
+ * can be used to filter log messages by it's type.
+ *
+ * @param sFileName
+ * the name of the log file (if nMode requires a log file)
+ */
+ public Protocol(int nMode ,
+ int nFilter ,
+ String sFileName)
+ {
+ m_nMode = nMode;
+ m_nFilter = nFilter;
+ m_sFileName = sFileName;
+ m_nLine = 0;
+ m_nScope = 1;
+ m_nWarnings = 0;
+ m_nErrors = 0;
+ m_aStartTime = new Timestamp(System.currentTimeMillis());
+ }
+
+ // ____________________
+ /**
+ * For some modes it's neccessary, that we write some additional
+ * informations to the log. E.g. for html we must generate close targets.
+ */
+ public synchronized void finish()
+ {
+ // Preferr HTML ... because we can't write ASCII and HTML contents to the same log file!
+ String sContent;
+ if ((m_nMode & MODE_HTML) == MODE_HTML)
+ sContent = impl_generateHTMLFooter();
+ else
+ if ((m_nMode & MODE_ASCII) == MODE_ASCII)
+ sContent = impl_generateAsciiFooter();
+ else
+ return;
+
+ impl_writeToLogFile(m_sFileName, true, sContent);
+ }
+
+ // ____________________
+ /**
+ * log an unspecified message.
+ *
+ * Sometimes it's not neccessary to set a special type for an message.
+ * The pure message seams to be enough. The type of such "pure messages"
+ * will be set to INFO.
+ *
+ * @param sMessage
+ * the pure message
+ *
+ * @see log(type,message)
+ */
+ public synchronized void log( /*IN*/ String sMessage )
+ {
+ log(TYPE_INFO, sMessage);
+ }
+
+ // ____________________
+ /**
+ * log an exception.
+ *
+ * It uses all informations available by this exception object
+ * to generate the log. So exceptions are printed out using a
+ * standard format.
+ *
+ * @param exThrowable
+ * the exception
+ */
+ public synchronized void log( /*IN*/ Throwable exThrowable )
+ {
+ log(TYPE_SCOPE_OPEN | TYPE_ERROR, "exception \""+exThrowable.getMessage()+"\"");
+
+ StackTraceElement[] lStack = exThrowable.getStackTrace();
+ for (int i=0; i<lStack.length; ++i)
+ log(TYPE_ERROR_INFO, lStack[i].toString());
+
+ log(TYPE_SCOPE_CLOSE | TYPE_ERROR_INFO, "");
+ }
+
+ // ____________________
+ /**
+ * log different property arrays.
+ *
+ * @param lProps
+ * the array of properties
+ */
+ public synchronized void log( /*IN*/ com.sun.star.beans.NamedValue[] lProps )
+ {
+ StringBuffer sValues = new StringBuffer(1000);
+ impl_logPropertyArray(sValues, lProps);
+
+ log(TYPE_SCOPE_OPEN | TYPE_INFO, "property array ["+lProps.length+"]:");
+ log(TYPE_SCOPE_CLOSE | TYPE_INFO, sValues.toString() );
+ }
+
+ public synchronized void log( /*IN*/ com.sun.star.beans.PropertyValue[] lProps )
+ {
+ StringBuffer sValues = new StringBuffer(1000);
+ impl_logPropertyArray(sValues, lProps);
+
+ log(TYPE_SCOPE_OPEN | TYPE_INFO, "property array ["+lProps.length+"]:");
+ log(TYPE_SCOPE_CLOSE | TYPE_INFO, sValues.toString() );
+ }
+
+ public synchronized void log( /*IN*/ com.sun.star.beans.NamedValue aProp )
+ {
+ StringBuffer sValue = new StringBuffer(1000);
+ impl_logProperty(sValue, aProp);
+
+ log(TYPE_SCOPE_OPEN | TYPE_INFO, "property:" );
+ log(TYPE_SCOPE_CLOSE | TYPE_INFO, sValue.toString());
+ }
+
+ public synchronized void log( /*IN*/ com.sun.star.beans.PropertyValue aProp )
+ {
+ StringBuffer sValue = new StringBuffer(1000);
+ impl_logProperty(sValue, aProp);
+
+ log(TYPE_SCOPE_OPEN | TYPE_INFO, "property:" );
+ log(TYPE_SCOPE_CLOSE | TYPE_INFO, sValue.toString());
+ }
+
+ public synchronized void log( /*IN*/ Object aAny )
+ {
+ StringBuffer sValue = new StringBuffer(1000);
+ impl_logAny(sValue, aAny);
+
+ log(TYPE_SCOPE_OPEN | TYPE_INFO, "any:" );
+ log(TYPE_SCOPE_CLOSE | TYPE_INFO, sValue.toString());
+ }
+
+ // ____________________
+ /**
+ * log a message.
+ *
+ * It looks for the internal set mode and decide, how this message
+ * will be handled. Then it generates a special object which represent
+ * one protocol line, format it and print it out.
+ *
+ * @param nType
+ * mark a line as a special one or open/close scopes
+ *
+ * @param sMessage
+ * the message, which the outside code wish to be written into the log
+ */
+ public synchronized void log( /*IN*/ int nType ,
+ /*IN*/ String sMessage )
+ {
+ nType = (nType & ~m_nFilter);
+ if (nType == 0)
+ return;
+
+ ++m_nLine;
+
+ // it's neccessary to open scopes before creatig the protocol line
+ // to guarantee right tab handling for new scope value!
+ if ((nType & TYPE_SCOPE_OPEN) == TYPE_SCOPE_OPEN)
+ ++m_nScope;
+
+ // create the protocol line
+ ProtocolLine aLine = new ProtocolLine(m_nLine, m_nScope, nType, sMessage);
+ String sAsciiLog = aLine.toString();
+ String sHTMLLog = aLine.toHTML();
+
+ // it's neccessary to close scope after creatig the protocol line
+ // to guarantee right tab handling for old scope value!
+ if (
+ ( m_nScope > 0 ) &&
+ ((nType & TYPE_SCOPE_CLOSE) == TYPE_SCOPE_CLOSE)
+ )
+ {
+ --m_nScope;
+ }
+
+ // update statistic values
+ if (aLine.isTestMark())
+ ++m_nTestMarks;
+ if (aLine.isWarning())
+ ++m_nWarnings;
+ if (aLine.isError())
+ ++m_nErrors;
+
+ // no else - it's a bit field of possible reactions!
+ if ((m_nMode & MODE_STDOUT) == MODE_STDOUT)
+ System.out.print(sAsciiLog);
+ // no else - it's a bit field of possible reactions!
+ if ((m_nMode & MODE_STDERR) == MODE_STDERR)
+ System.err.print(sAsciiLog);
+ // no else - it's a bit field of possible reactions!
+ // But these both conditions must be handled together.
+ // Because we cant generate different types of log contents to the same log file.
+ // We preferr HTML if both types are set.
+ if (
+ ((m_nMode & MODE_HTML ) == MODE_HTML ) ||
+ ((m_nMode & MODE_ASCII) == MODE_ASCII)
+ )
+ {
+ boolean bAppend = (m_nLine>1);
+ String sContent;
+ if ((m_nMode & MODE_HTML) == MODE_HTML)
+ {
+ if (! bAppend)
+ sContent = impl_generateHTMLHeader()+sHTMLLog;
+ else
+ sContent = sHTMLLog;
+ }
+ else
+ {
+ if (! bAppend)
+ sContent = impl_generateAsciiHeader()+sAsciiLog;
+ else
+ sContent = sAsciiLog;
+ }
+
+ impl_writeToLogFile(m_sFileName, bAppend, sContent);
+ }
+ }
+
+ // ____________________
+ public synchronized void defineHyperlink( /*IN*/ String sTarget ,
+ /*IN*/ String sDescription)
+ {
+ if ((m_nMode & MODE_HTML) != MODE_HTML)
+ return;
+
+ StringBuffer sLog = new StringBuffer(1000);
+ sLog.append("<a href=\"");
+ sLog.append(sTarget );
+ sLog.append("\">" );
+ sLog.append(sDescription);
+ sLog.append("</a>" );
+
+ log(TYPE_LINK, sLog.toString());
+ }
+
+ // ____________________
+ /**
+ * log the current statistic values
+ * We write it into our protocol buffer and
+ * reset it.
+ */
+ public synchronized void logStatistics()
+ {
+ m_aEndTime = new Timestamp(System.currentTimeMillis());
+ Timestamp aDiff = new Timestamp(m_aEndTime.getTime()-m_aStartTime.getTime());
+
+ int nLogType = TYPE_STATISTIC;
+ if (m_nErrors > 0)
+ nLogType = TYPE_ERROR_INFO;
+ else
+ if (m_nWarnings > 0)
+ nLogType = TYPE_WARNING_INFO;
+
+ log(nLogType | TYPE_SCOPE_OPEN , "statistic:" );
+ log(nLogType , "tests = "+m_nTestMarks );
+ log(nLogType , "errors = "+m_nErrors );
+ log(nLogType , "warnings = "+m_nWarnings );
+ log(nLogType , "elapsed time = "+aDiff.toString());
+ log(nLogType | TYPE_SCOPE_CLOSE, "" );
+
+ resetStatistics();
+ }
+
+ public synchronized void resetStatistics()
+ {
+ m_nTestMarks = 0;
+ m_nWarnings = 0;
+ m_nErrors = 0;
+ m_aStartTime = new Timestamp(System.currentTimeMillis());
+ }
+
+ // ____________________
+ /**
+ * returns a generic html header for generating html log files
+ *
+ * It's used from the method finish() to generate a valid html formated file.
+ * For that its neccessary to open some special html targets like e.g. <html>.
+ *
+ * @return A string, which includes the whole header.
+ *
+ * @see finish()
+ * @see generateHTMLFooter()
+ */
+ private String impl_generateHTMLHeader()
+ {
+ return "<html>\n<head>\n<title>"+m_sFileName+"</title>\n</head>\n<body>\n<table>\n";
+ }
+
+ private String impl_generateAsciiHeader()
+ {
+ return "********************************************************************************\n";
+ }
+
+ private String impl_generateHTMLFooter()
+ {
+ return "\n</table>\n</body>\n</html>\n";
+ }
+
+ private String impl_generateAsciiFooter()
+ {
+ return "\n\n";
+ }
+
+ // ____________________
+ /**
+ * helper to log different representations of a property(array)
+ *
+ * @param sOut
+ * used to generate the log output there.
+ *
+ * @param lProps/aProp
+ * represent the property(array) to be logged.
+ */
+ private void impl_logPropertyArray( /*OUT*/ StringBuffer sOut ,
+ /*IN */ com.sun.star.beans.PropertyValue[] lProps )
+ {
+ int i = 0;
+ int c = lProps.length;
+
+ for (i=0; i<c; ++i)
+ impl_logProperty(sOut, lProps[i]);
+ }
+
+ private void impl_logPropertyArray( /*OUT*/ StringBuffer sOut ,
+ /*IN */ com.sun.star.beans.NamedValue[] lProps )
+ {
+ int i = 0;
+ int c = lProps.length;
+
+ for (i=0; i<c; ++i)
+ impl_logProperty(sOut, lProps[i]);
+ }
+
+ private void impl_logProperty( /*OUT*/ StringBuffer sOut ,
+ /*IN*/ com.sun.star.beans.NamedValue aProp )
+ {
+ sOut.append("\""+aProp.Name+"\" = ");
+ impl_logAny(sOut, aProp.Value);
+ }
+
+ private void impl_logProperty( /*OUT*/ StringBuffer sOut ,
+ /*IN*/ com.sun.star.beans.PropertyValue aProp )
+ {
+ sOut.append("\""+aProp.Name+"\" = ");
+ impl_logAny(sOut, aProp.Value);
+ }
+
+ // ____________________
+ /**
+ * it trys to convert the given any into a suitable string notation .-)
+ */
+ private synchronized void impl_logAny( /*OUT*/ StringBuffer sOut ,
+ /*IN */ Object aAny )
+ {
+ try
+ {
+ if (com.sun.star.uno.AnyConverter.isVoid(aAny))
+ {
+ sOut.append("[void] {");
+ }
+ else
+ if (com.sun.star.uno.AnyConverter.isChar(aAny))
+ {
+ sOut.append("[char] {");
+ sOut.append(com.sun.star.uno.AnyConverter.toChar(aAny));
+ sOut.append("}");
+ }
+ else
+ if (com.sun.star.uno.AnyConverter.isBoolean(aAny))
+ {
+ sOut.append("[boolean] {");
+ if (com.sun.star.uno.AnyConverter.toBoolean(aAny))
+ sOut.append("TRUE");
+ else
+ sOut.append("FALSE");
+ sOut.append("}");
+ }
+ else
+ if (com.sun.star.uno.AnyConverter.isByte(aAny))
+ {
+ sOut.append("[byte] {");
+ sOut.append(com.sun.star.uno.AnyConverter.toByte(aAny));
+ sOut.append("}");
+ }
+ else
+ if (com.sun.star.uno.AnyConverter.isShort(aAny))
+ {
+ sOut.append("[short] {");
+ sOut.append(com.sun.star.uno.AnyConverter.toShort(aAny));
+ sOut.append("}");
+ }
+ else
+ if (com.sun.star.uno.AnyConverter.isInt(aAny))
+ {
+ sOut.append("[int] {");
+ sOut.append(com.sun.star.uno.AnyConverter.toInt(aAny));
+ sOut.append("}");
+ }
+ else
+ if (com.sun.star.uno.AnyConverter.isLong(aAny))
+ {
+ sOut.append("[long] {");
+ sOut.append(com.sun.star.uno.AnyConverter.toLong(aAny));
+ sOut.append("}");
+ }
+ else
+ if (com.sun.star.uno.AnyConverter.isFloat(aAny))
+ {
+ sOut.append("[float] {");
+ sOut.append(com.sun.star.uno.AnyConverter.toFloat(aAny));
+ sOut.append("}");
+ }
+ else
+ if (com.sun.star.uno.AnyConverter.isDouble(aAny))
+ {
+ sOut.append("[double] {");
+ sOut.append(com.sun.star.uno.AnyConverter.toDouble(aAny));
+ sOut.append("}");
+ }
+ else
+ if (com.sun.star.uno.AnyConverter.isString(aAny))
+ {
+ sOut.append("[string] {");
+ sOut.append(com.sun.star.uno.AnyConverter.toString(aAny));
+ sOut.append("}");
+ }
+ else
+ if (com.sun.star.uno.AnyConverter.isEnum(aAny))
+ {
+ sOut.append("[enum] {");
+ sOut.append("}");
+ }
+ else
+ if (com.sun.star.uno.AnyConverter.isType(aAny))
+ {
+ sOut.append("[type] {");
+ sOut.append("}");
+ }
+ else
+ if (com.sun.star.uno.AnyConverter.isArray(aAny))
+ {
+ if (aAny instanceof java.lang.String[])
+ {
+ sOut.append("[sequence< string >] {");
+ sOut.append("}");
+ }
+ else
+ if (aAny instanceof com.sun.star.beans.PropertyValue[])
+ {
+ sOut.append("[sequence< PropertyValue >] {");
+ com.sun.star.beans.PropertyValue[] lSubProps = (com.sun.star.beans.PropertyValue[])com.sun.star.uno.AnyConverter.toArray(aAny);
+ impl_logPropertyArray(sOut, lSubProps);
+ sOut.append("}");
+ }
+ else
+ if (aAny instanceof com.sun.star.beans.NamedValue[])
+ {
+ sOut.append("[sequence< NamedValue >] {");
+ com.sun.star.beans.NamedValue[] lSubProps = (com.sun.star.beans.NamedValue[])com.sun.star.uno.AnyConverter.toArray(aAny);
+ impl_logPropertyArray(sOut, lSubProps);
+ sOut.append("}");
+ }
+ else
+ {
+ sOut.append("[unknown array] {-}");
+ }
+ }
+ else
+ if (com.sun.star.uno.AnyConverter.isObject(aAny))
+ {
+ sOut.append("[object] {");
+ // TODO
+ sOut.append("}");
+ }
+
+ if ((m_nMode & MODE_HTML) == MODE_HTML)
+ sOut.append("<br>");
+ else
+ sOut.append("\n");
+ }
+ catch(com.sun.star.lang.IllegalArgumentException exIll)
+ {
+ sOut.append("Got exception during property conversion.\n");
+ sOut.append(exIll.getMessage());
+ sOut.append("\n");
+ }
+ }
+
+ // ____________________
+ /**
+ * Writes the given content to the specified log file.
+ */
+ private void impl_writeToLogFile(String sFileName,
+ boolean bAppend ,
+ String sContent )
+ {
+ try
+ {
+ FileWriter aLogFile = new FileWriter(sFileName, bAppend);
+ aLogFile.write(sContent);
+ aLogFile.flush();
+ aLogFile.close();
+ aLogFile = null;
+ }
+ catch (java.io.IOException exIO)
+ {
+ System.err.println("Can't dump protocol into log file.");
+ System.err.println(exIO);
+ exIO.printStackTrace();
+ }
+ }
+}
diff --git a/framework/qa/complex/framework/autosave/makefile.mk b/framework/qa/complex/framework/autosave/makefile.mk
new file mode 100644
index 000000000000..e903c9ad5f33
--- /dev/null
+++ b/framework/qa/complex/framework/autosave/makefile.mk
@@ -0,0 +1,89 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org 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 Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+PRJ = ..$/..$/..$/..
+TARGET = AutoSave
+PRJNAME = framework
+PACKAGE = complex$/framework$/autosave
+
+# --- Settings -----------------------------------------------------
+.INCLUDE: settings.mk
+
+
+#----- compile .java files -----------------------------------------
+
+JARFILES = mysql.jar ridl.jar unoil.jar jurt.jar juh.jar java_uno.jar \
+ OOoRunner.jar mysql.jar
+JAVAFILES = AutoSave.java ConfigHelper.java Protocol.java
+JAVACLASSFILES = $(foreach,i,$(JAVAFILES) $(CLASSDIR)$/$(PACKAGE)$/$(i:b).class)
+
+#----- make a jar from compiled files ------------------------------
+
+MAXLINELENGTH = 100000
+
+JARCLASSDIRS = $(PACKAGE)
+JARTARGET = $(TARGET).jar
+JARCOMPRESS = TRUE
+
+# --- Parameters for the test --------------------------------------
+
+# start an office if the parameter is set for the makefile
+.IF "$(OFFICE)" == ""
+CT_APPEXECCOMMAND =
+.ELSE
+CT_APPEXECCOMMAND = -AppExecutionCommand "$(OFFICE)$/soffice -accept=socket,host=localhost,port=8100;urp;"
+.ENDIF
+
+# test base is java complex
+CT_TESTBASE = -TestBase java_complex
+
+# test looks something like the.full.package.TestName
+CT_TEST = -o $(PACKAGE:s\$/\.\).$(JAVAFILES:b)
+
+# start the runner application
+CT_APP = org.openoffice.Runner
+
+# --- Targets ------------------------------------------------------
+
+.IF "$(depend)" == ""
+$(CLASSDIR)$/$(PACKAGE)$/$(JAVAFILES:b).props : ALLTAR
+.ELSE
+$(CLASSDIR)$/$(PACKAGE)$/$(JAVAFILES:b).props : ALLDEP
+.ENDIF
+
+.INCLUDE : target.mk
+
+#$(CLASSDIR)$/$(PACKAGE)$/$(JAVAFILES:b).props : $(JAVAFILES:b).props
+# cp $(JAVAFILES:b).props $(CLASSDIR)$/$(PACKAGE)$/$(JAVAFILES:b).props
+# jar uf $(CLASSDIR)$/$(JARTARGET) -C $(CLASSDIR) $(PACKAGE)$/$(JAVAFILES:b).props
+
+RUN: run
+
+run:
+ +java -cp $(CLASSPATH) $(CT_APP) $(CT_TESTBASE) $(CT_APPEXECCOMMAND) $(CT_TEST)
+
+
+
diff --git a/framework/qa/complex/framework/recovery/CrashThread.java b/framework/qa/complex/framework/recovery/CrashThread.java
new file mode 100644
index 000000000000..616d4baa200e
--- /dev/null
+++ b/framework/qa/complex/framework/recovery/CrashThread.java
@@ -0,0 +1,80 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package complex.framework.recovery;
+
+import com.sun.star.frame.XController;
+import com.sun.star.frame.XDispatch;
+import com.sun.star.frame.XDispatchProvider;
+import com.sun.star.frame.XModel;
+import com.sun.star.lang.XComponent;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.util.URL;
+import com.sun.star.util.XURLTransformer;
+
+/**
+ * Thread to crash the office. This thread dies after the office process
+ * is nopt longer available.
+ */
+public class CrashThread extends Thread {
+ public XComponent xDoc = null;
+ public XMultiServiceFactory msf = null;
+
+ public CrashThread(XComponent xDoc, XMultiServiceFactory msf) {
+ this.xDoc = xDoc;
+ this.msf = msf;
+ }
+
+ public void run() {
+ try{
+ XModel xModel = (XModel) UnoRuntime.queryInterface(XModel.class, xDoc);
+
+ XController xController = xModel.getCurrentController();
+ XDispatchProvider xDispProv = (XDispatchProvider) UnoRuntime.queryInterface(
+ XDispatchProvider.class,
+ xController);
+ XURLTransformer xParser = (XURLTransformer) UnoRuntime.queryInterface(
+ XURLTransformer.class,
+ msf.createInstance(
+ "com.sun.star.util.URLTransformer"));
+
+ // Because it's an in/out parameter we must use an array of URL objects.
+ URL[] aParseURL = new URL[1];
+ aParseURL[0] = new URL();
+ aParseURL[0].Complete = ".uno:Crash";
+ xParser.parseStrict(aParseURL);
+
+ URL aURL = aParseURL[0];
+ XDispatch xDispatcher = xDispProv.queryDispatch(aURL, "", 0);
+
+ if (xDispatcher != null) {
+ xDispatcher.dispatch(aURL, null);
+ }
+ } catch (Exception e){}
+ }
+}
diff --git a/framework/qa/complex/framework/recovery/KlickButtonThread.java b/framework/qa/complex/framework/recovery/KlickButtonThread.java
new file mode 100644
index 000000000000..426a2e3d2a79
--- /dev/null
+++ b/framework/qa/complex/framework/recovery/KlickButtonThread.java
@@ -0,0 +1,57 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package complex.framework.recovery;
+
+import com.sun.star.awt.XWindow;
+import com.sun.star.lang.XMultiServiceFactory;
+import util.UITools;
+
+/**
+ * Thread to crash the office. This thread dies after the office process
+ * is nopt longer available.
+ */
+public class KlickButtonThread extends Thread {
+ private XWindow xWindow = null;
+ private XMultiServiceFactory xMSF = null;
+ private String buttonName = null;
+
+ public KlickButtonThread(XMultiServiceFactory xMSF, XWindow xWindow, String buttonName) {
+ this.xWindow = xWindow;
+ this.xMSF = xMSF;
+ this.buttonName = buttonName;
+ }
+
+ public void run() {
+ try{
+ UITools oUITools = new UITools(xMSF, xWindow);
+
+ oUITools.clickButton(buttonName);
+
+ } catch (Exception e){}
+ }
+}
diff --git a/framework/qa/complex/framework/recovery/RecoveryTest.java b/framework/qa/complex/framework/recovery/RecoveryTest.java
new file mode 100644
index 000000000000..ee565ff74330
--- /dev/null
+++ b/framework/qa/complex/framework/recovery/RecoveryTest.java
@@ -0,0 +1,1012 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package complex.framework.recovery;
+
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.awt.Rectangle;
+import com.sun.star.awt.Size;
+import com.sun.star.awt.XDialog;
+import com.sun.star.awt.XExtendedToolkit;
+import com.sun.star.awt.XWindow;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.container.XEnumeration;
+import com.sun.star.container.XIndexAccess;
+import com.sun.star.container.XNameContainer;
+import com.sun.star.drawing.XDrawPage;
+import com.sun.star.drawing.XDrawPages;
+import com.sun.star.drawing.XDrawPagesSupplier;
+import com.sun.star.drawing.XShape;
+import com.sun.star.drawing.XShapes;
+import com.sun.star.frame.XController;
+import com.sun.star.frame.XDesktop;
+import com.sun.star.frame.XDispatch;
+import com.sun.star.frame.XDispatchProvider;
+import com.sun.star.frame.XFrame;
+import com.sun.star.frame.XModel;
+import com.sun.star.lang.XComponent;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.lang.XSingleServiceFactory;
+import com.sun.star.presentation.XCustomPresentationSupplier;
+import com.sun.star.presentation.XPresentationSupplier;
+import com.sun.star.sheet.XSheetCellRange;
+import com.sun.star.sheet.XSpreadsheet;
+import com.sun.star.sheet.XSpreadsheetDocument;
+import com.sun.star.sheet.XSpreadsheets;
+import com.sun.star.style.XStyle;
+import com.sun.star.table.XCellRange;
+import com.sun.star.text.ControlCharacter;
+import com.sun.star.text.XText;
+import com.sun.star.text.XTextCursor;
+import com.sun.star.text.XTextDocument;
+import com.sun.star.uno.AnyConverter;
+import com.sun.star.uno.Type;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.XInterface;
+import com.sun.star.view.XSelectionSupplier;
+import complexlib.ComplexTestCase;
+import helper.OfficeProvider;
+import helper.OfficeWatcher;
+import java.awt.Dimension;
+import java.awt.Point;
+import java.awt.Toolkit;
+import java.io.PrintWriter;
+import java.util.Hashtable;
+import java.util.Random;
+import util.DesktopTools;
+import util.PropertyName;
+import util.SOfficeFactory;
+import util.UITools;
+import util.utils;
+
+public class RecoveryTest extends ComplexTestCase {
+
+ static XMultiServiceFactory xMSF;
+ static SOfficeFactory SOF;
+ static RecoveryTools rt;
+ /**
+ * If you devid the screen in four parts in the first of them the office
+ * windows should be placed. The range of the first quarter is stored in the variable.
+ */
+ static Point windowMaxPosition;
+ /**
+ * The office windows starts in the first quarter of the screen. In this variable
+ * the maximum size for the windows was stored so the windows can be placed
+ * visible on the screen.
+ */
+ static Size windowMaxSize;
+
+ /**
+ * All office windows will be placed by this test on randomized positions.
+ * This positions was stored in this Hashmap. The keys are the frame names
+ * and the values are com sun.star.awt.Rectangle.
+ * @see com.sun.star.awt.Rectangle
+ */
+ private Hashtable windowsPosSize = new Hashtable();
+
+ /**
+ * A function to tell the framework, which test functions are available.
+ * @return All test methods.
+ *
+ * @todo: hidden documents
+ * @todo: running presentation
+ * @todo: modular dialogs like Hpyerlink-Dialog
+ * @todo: sceond view of a document
+ * @todo: remove recovery data before start test
+ * @todo: after a second start after the crash there should no documents recovered anymore
+ * @todo: enable remove of recovery files
+ * @todo: makefile anpassen auf Parameter überprüfen
+ */
+ public String[] getTestMethodNames() {
+ return new String[]{"testCrash"};
+ }
+
+ /** Create the environment for following tests.
+ * Use either a component loader from desktop or
+ * from frame
+ * @throws Exception Exception
+ */
+
+ public void normalCrash(){
+ cleanRecoveryData();
+ startOffice();
+ generateDesktop();
+ makeCrash();
+ int expectedDocumentCount = windowsPosSize.size() + 1;
+ handleRecoveryDialogAfterCrash(expectedDocumentCount);
+ startOffice();
+ handleRecoveryDialog_QuickExit(expectedDocumentCount);
+ handleCrashReporterDialog(true, true);
+ checkDocumentCount(expectedDocumentCount);
+ }
+
+ public void testCrash(){
+ cleanRecoveryData();
+ restoreBackupRecoveryData();
+ startOffice();
+ int expectedDocumentCount = 3;
+// handleRecoveryDialog_QuickExit(expectedDocumentCount);
+ handleRecoveryDialog_QuickExitAndSave(expectedDocumentCount);
+ //handleCrashReporterDialog(true, true);
+ //checkDocumentCount(expectedDocumentCount);
+ }
+
+ public void before() throws Exception {
+
+ String msg ="\n\n\tPATH TO OFFICE BINARY MISSING!\n";
+ msg +="\tPlease run your command with the following parameter:\n\n";
+ msg +="\t-AppExecutionCommand=OFFICEBINARY CONNECTIONSTRING\n\n";
+ msg +="Example Windows:\n";
+ msg +="-AppExecutionCommand=C:\\office\\soffice.exe -accept=socket,host=localhost,port=8101;urp;\n\n";
+ msg +="Example UNIX:\n";
+ msg +="-AppExecutionCommand=/office/soffice \"-accept=socket,host=localhost,port=8101;urp;\"\n\n";
+ msg+="NOTE: on UNIX be shure to have the connection string inside quotation mark!\n";
+
+ assure(msg, param.get("AppExecutionCommand") != null && ! param.get("AppExecutionCommand").equals(""));
+ System.out.println("HALLO" + param.get("AppExecutionCommand"));
+ msg = "\n\nONE PARAMETER IS MISSING!\n";
+ msg += "Please append to your command the following parameter:\n\n";
+ msg += "\t-NoOffice=true";
+ assure(msg, param.getBool("NoOffice"));
+
+
+ rt = new RecoveryTools(param ,log);
+
+ rt.removeParametersFromAppExecutionCommand();
+
+ log.println("start the office to test recovery feature...");
+
+ // make window ranges
+ makeWindowPositionRage();
+
+ //makeRecoveryData();
+ }
+
+ private void makeRecoveryData(){
+ cleanRecoveryData();
+ startOffice();
+ generateDesktop();
+ makeCrash();
+ int expectedDocumentCount = windowsPosSize.size() + 1;
+ handleRecoveryDialogAfterCrash(expectedDocumentCount);
+ backupRecoveryData();
+ cleanRecoveryData();
+ }
+
+ private void startOffice(){
+ assure("Could not connect to office", connect());
+ log.setWatcher(param.get("Watcher"));
+ }
+
+
+ private void checkDocumentCount(int expectedDocumentCount){
+ XEnumeration allComp = DesktopTools.getAllComponents(xMSF);
+ int documentCount = 0;
+
+ try{
+ while (allComp.hasMoreElements()){
+ allComp.nextElement();
+ documentCount ++;
+ }
+ }
+ catch ( com.sun.star.container.NoSuchElementException e){}
+ catch ( com.sun.star.lang.WrappedTargetException e){}
+
+ String msg ="The amount of documents to recover is different form the expected amount:\n";
+ msg += "\texpected:\t" + expectedDocumentCount + "\n";
+ msg += "\tto recover:\t" + documentCount;
+
+ assure(msg, expectedDocumentCount == documentCount);
+ }
+
+ /**
+ * This function starts an office instance. It uses the AppExecutionCommad parameter.
+ * @return TRUE if office is connected otherwise FALSE
+ */
+ private boolean connect(){
+ try {
+
+ OfficeProvider oProvider = new OfficeProvider();
+ xMSF = (XMultiServiceFactory)oProvider.getManager(param);
+
+ SOF = SOfficeFactory.getFactory(xMSF);
+
+ }
+ catch (java.lang.Exception e) {
+ log.println(e.getClass().getName());
+ log.println("Message: " + e.getMessage());
+ failed("Cannot connect the Office.");
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * While creating the test environment the positions and sizes of the frames
+ * was saved. After the Office has recovered the documents, this functions
+ * compares the saved positions and sizes with the current frame.
+ */
+ private void compareWindowPositions(){
+ System.out.println("all frames:########");
+ System.out.println(windowsPosSize.entrySet().toString());
+
+ XEnumeration allComp = DesktopTools.getAllComponents(xMSF);
+
+ String msg=null;
+
+ while (allComp.hasMoreElements()){
+ try{
+ // get all components from the desktop
+ XComponent xComponent = (XComponent) UnoRuntime.queryInterface(
+ XComponent.class, allComp.nextElement());
+
+ XModel xModel = (XModel) UnoRuntime.queryInterface(XModel.class, xComponent);
+
+ String frameName = xModel.getCurrentController().getFrame().getName();
+
+ // check if this frame was used in creation of test environment
+ if (windowsPosSize.containsKey(frameName)){
+
+ Rectangle oldRect = (Rectangle) windowsPosSize.get(frameName);
+
+ XWindow xWindow = xModel.getCurrentController().getFrame().getContainerWindow();
+ Rectangle newRect = xWindow.getPosSize();
+
+
+ boolean ok = oldRect.Height == newRect.Height;
+ ok &= oldRect.Width == newRect.Width;
+ ok &= oldRect.X == newRect.X;
+ ok &= oldRect.Y == newRect.Y;
+
+ if (!ok){
+ msg = "The frame '" + frameName + "' has a different position/size:\n";
+ msg += "original value -> restored value:\n";
+ msg += "X : " + oldRect.X + " -> " + newRect.X + "\n";
+ msg += "Y : " + oldRect.Y + " -> " + newRect.Y + "\n";
+ msg += "Height: " + oldRect.Height + " -> " + newRect.Height + "\n";
+ msg += "Width : " + oldRect.Width + " -> " + newRect.Width + "\n";
+ }
+
+ assure(msg, ok, CONTINUE);
+
+ }
+ } catch (com.sun.star.container.NoSuchElementException e) {
+ } catch ( com.sun.star.lang.WrappedTargetException e) {}
+ }
+
+ }
+
+ /**
+ * This function crashes the office
+ */
+ private void makeCrash(){
+ // get all documents
+ Object[] allDocs = DesktopTools.getAllOpenDocuments(xMSF);
+
+ // get one of them for dispatching
+ XComponent xDoc = (XComponent) allDocs[0];
+ log.println("make the crash in second thread");
+
+ CrashThread crash = new CrashThread(xDoc, xMSF);
+ crash.start();
+ rt.pause();
+ rt.pause();
+ }
+
+ /**
+ * This function uses accessibility to handle the dialog which appears while the
+ * office is crashed. It click the button "OK" to continue.
+ */
+ private void handleRecoveryDialogAfterCrash(int expectedDocumentCount){
+ try{
+
+ // if the office crashes, the recovery feature needs some time
+ // to save all docs. Therefore the recovery dialog could need some
+ // time to pop up.
+ log.println("wating for recovery dialog...");
+
+ int counter = 0;
+ int maximum = param.getInt(PropertyName.THREAD_TIME_OUT) / param.getInt(PropertyName.SHORT_WAIT);
+
+ XDialog oDialog = rt.getActiveDialog(xMSF);
+
+ while ( oDialog == null && (counter < maximum))
+ {
+ rt.pause();
+ oDialog = rt.getActiveDialog(xMSF);
+ counter ++;
+ }
+
+ assure("could not get Recovery Window",(oDialog != null));
+
+ XWindow xWindow = (XWindow) UnoRuntime.queryInterface(XWindow.class, oDialog);
+
+ UITools oUITools = new UITools(xMSF, xWindow);
+
+ oUITools.printAccessibleTree((PrintWriter) log, param.getBool(PropertyName.DEBUG_IS_ACTIVE));
+
+ String[] documents = oUITools.getListBoxItems("The following files will be recovered");
+ log.println("there are " + documents.length + " documents to save");
+
+ String msg ="The amount of documents to recover is different form the expected amount:\n";
+ msg += "\texpected:\t" + expectedDocumentCount + "\n";
+ msg += "\tto recover:\t" + documents.length;
+
+ assure(msg, expectedDocumentCount == documents.length);
+
+ log.println("disable automatically launch of Office");
+ oUITools.setCheckBoxValue("Launch StarOffice automatically", new Integer(0));
+
+ log.println("start saving...");
+ oUITools.clickButton("OK");
+
+ rt.waitForClosedOffice();
+
+ } catch (Exception e){
+ e.printStackTrace();
+ failed("Could not handle crash-dialog: " + e.toString());
+ }
+ }
+
+ private void handleCrashReporterDialog(boolean cancel, boolean YesNo){
+ try{
+
+ log.println("try to get Crash Reporter Dialog...");
+
+ XDialog oDialog = rt.getActiveDialog(xMSF);
+ assure("could not get CrashReporter Dialog", oDialog != null);
+
+ XWindow xWindow = (XWindow) UnoRuntime.queryInterface(XWindow.class, oDialog);
+
+ log.println(oDialog.getTitle());
+
+ UITools oUITools = new UITools(xMSF, xWindow);
+
+ if (cancel) {
+ log.println("clicking 'Cancel' button...");
+
+ try{
+ rt.clickThreadButton(xMSF, xWindow, "Cancel");
+ } catch (com.sun.star.accessibility.IllegalAccessibleComponentStateException e){
+ failed("Could not click 'Cancel' at CrashReporter Dialog");
+ }
+
+ }
+ else {
+ log.println("clicking 'Next' button...");
+ oUITools.clickButton("Next>>");
+ }
+
+ } catch (Exception e){
+ failed("Could not handle CrashReporter Dialog: " + e.toString());
+ }
+ }
+
+ private void handleRecoveryDialog_QuickExit(int expectedDocumentCount){
+ log.println("handle Recovery Dialog at restart: quick exit");
+ handleRecoveryDialogAtRestart(expectedDocumentCount, false, true);
+ handleAreYouSureDialog(true);
+ handleSaveDocumentsDialog(false);
+
+ }
+ private void handleRecoveryDialog_QuickExitAndSave(int expectedDocumentCount){
+ log.println("handle Recovery Dialog at restart: quick exit");
+ handleRecoveryDialogAtRestart(expectedDocumentCount, false, true);
+ handleAreYouSureDialog(true);
+ handleSaveDocumentsDialog(true);
+ }
+ private void handleRecoveryDialog_Recover(int expectedDocumentCount){
+
+ }
+ private void handleRecoveryDialog_RecoverAndCrashreporter(int expectedDocumentCount){
+
+ }
+ /**
+ * This function uses accessibility to handle the dialog which appears while the
+ * office is started after a crash. It waits until the "next>>" button is enabled
+ * and click it then to continue.
+ * @param expectedDocumentCount the amount of documents which must be displayed in the recovery dialog
+ * @param recover If the documenst should be recoverd this variable must be true. If it is fasle
+ * the recovery process was stoped and the button cancel was klicked.
+ * @param cancel If the recovery is fifnished, this parameter desicdes to klick the "Next" button
+ * or the click cancel. If the value is true, the cancel button was clicked.
+ */
+ private void handleRecoveryDialogAtRestart(int expectedDocumentCount, boolean recover, boolean cancel){
+ try{
+
+ log.println("try to get Recovery Dialog...");
+
+ XDialog oDialog = null;
+ oDialog = rt.getActiveDialogAfterStartup(xMSF);
+
+ assure("could not get Recovery Dialog at start of office", (oDialog != null), CONTINUE);
+
+ XWindow xWindow = (XWindow) UnoRuntime.queryInterface(XWindow.class, oDialog);
+ log.println("got the following dialog: '" +oDialog.getTitle() + "'");
+
+ UITools oUITools = new UITools(xMSF, xWindow);
+
+ String listBoxName = "Status of recovered documents";
+ String[] documents = oUITools.getListBoxItems(listBoxName);
+ log.println("there are " + documents.length + " documents to recover");
+ log.println("The following files will be recovered:");
+ for (int i=0;i<documents.length;i++){
+ log.println(documents[i]);
+ }
+
+ String msg ="The amount of documents to recover is different form the expected amount:\n";
+ msg += "\texpected:\t" + expectedDocumentCount + "\n";
+ msg += "\tto recover:\t" + documents.length;
+
+ assure(msg, expectedDocumentCount ==documents.length);
+
+ if (recover){
+
+ log.println("clicking 'Start Recovery' button...");
+ oUITools.clickButton("Start Recovery >");
+
+ rt.pause();
+
+ //XAccessibleContext oButton = oUITools.getButton("Start Recovery >");
+ int counter = 0;
+ int maximum = param.getInt(PropertyName.THREAD_TIME_OUT) / param.getInt(PropertyName.SHORT_WAIT);
+ //boolean enabeld = oButton.getAccessibleStateSet().contains(com.sun.star.accessibility.AccessibleStateType.ENABLED);
+
+ XAccessibleContext oButton = null;
+ while ((oButton == null) && (counter < maximum)){
+ log.println("recovering...");
+
+ try{
+ oButton = oUITools.getButton("Next >");
+ } catch (java.lang.NullPointerException e){
+ // no fault: The title "Start Recovery" switches to "Next"
+ // while all documents are recoverd
+ }
+ rt.pause();
+ counter++;
+ }
+
+ if (cancel) {
+ log.println("clicking 'Cancel' button...");
+
+ try{
+ rt.clickThreadButton(xMSF, xWindow, "Cancel");
+ } catch (com.sun.star.accessibility.IllegalAccessibleComponentStateException e){
+ failed("Could not click 'Cancel' at recovery-dialog.");
+ }
+
+ }
+ else {
+ log.println("clicking 'Next' button...");
+ oUITools.clickButton("Next >");
+ }
+
+ rt.pause();
+
+ } else {
+ log.println("do not recover: clicking 'Cancel' button...");
+
+ try{
+ rt.clickThreadButton(xMSF, xWindow, "Cancel");
+ } catch (com.sun.star.accessibility.IllegalAccessibleComponentStateException e){
+ failed("Could not click 'Cancel' at recovery-dialog");
+ }
+ }
+
+ } catch (Exception e){
+ failed("Could not handle recovery-dialog at restart: " + e.toString());
+ }
+
+ }
+
+ /**
+ * This function uses accessibility to handle the dialog "Are you sure".
+ * It cklick "Yes" or "No", dependend on the value of the parameter <CODE>Yes</CODE>
+ * @param yes If value is <CODE>TRUE</CODE> the button "Yes" was clicked, otherwise the button
+ * "No".
+ */
+ private void handleAreYouSureDialog(boolean yes)
+ {
+ try{
+ if (yes){
+ rt.handleModalDialog(xMSF, "Yes");
+ } else{
+ rt.handleModalDialog(xMSF, "Cancel");
+ }
+ } catch (com.sun.star.accessibility.IllegalAccessibleComponentStateException e){
+ failed("Could not handle 'Are you sure' dialog.");
+ }
+ }
+
+ /**
+ * This function uses accessibility to handle the dialog "Are you sure".
+ * It cklick "Yes" or "No", dependend on the value of the parameter <CODE>Yes</CODE>
+ * @param yes If value is <CODE>TRUE</CODE> the button "Yes" was clicked, otherwise the button
+ * "No".
+ */
+ private void handleSaveDocumentsDialog(boolean saveDocuments)
+ {
+ try{
+ if (!saveDocuments){
+ rt.handleModalDialog(xMSF, "Cancel");
+ } else{
+ XWindow oDialog = null;
+ oDialog = rt.getActiveWindow(xMSF);
+
+ assure("could not get 'Save Documents' Dialog: ", (oDialog != null), CONTINUE);
+
+ UITools oUITools = new UITools(xMSF, oDialog);
+
+ oUITools.printAccessibleTree((PrintWriter) log, param.getBool(PropertyName.DEBUG_IS_ACTIVE));
+
+ String listBoxName = "Documents";
+ String[] documents = null;
+ try{
+ documents = oUITools.getListBoxItems(listBoxName);
+ } catch (java.lang.Exception e){
+ failed("could not get the document names from the 'Save Documents' dialog", CONTINUE);
+ }
+ log.println("there are " + documents.length + " documents to save");
+ log.println("The following documents will be saved:");
+ for (int i=0;i<documents.length;i++){
+ log.println(documents[i]);
+ }
+ String tempURL = utils.getOfficeTempDir(xMSF);
+
+ log.println("the destination for saveing is: " + tempURL);
+ try{
+ oUITools.setTextEditFiledText("Save to", tempURL);
+ } catch (java.lang.Exception e){
+ failed("could not set target directory for saving documents at 'Save Documents' dialog", CONTINUE);
+ }
+ try{
+ oUITools.clickButton("OK");
+ } catch (java.lang.Exception e){
+ failed("could not click 'OK' at 'Save Documents' dialog", CONTINUE);
+ }
+ }
+ } catch (com.sun.star.accessibility.IllegalAccessibleComponentStateException e){
+ failed("Could not handle 'Are you sure' dialog.");
+ }
+ }
+
+ /**
+ * This function gets the current screen size and calculate the first
+ * quarter of it. This qaurter was used to postion to Office windows.
+ * Further this function calculates the maximum window size so the window
+ * is visible if it placed on extreme position.
+ */
+ private void makeWindowPositionRage(){
+ Dimension screenDim = Toolkit.getDefaultToolkit().getScreenSize();
+ Point pos = new Point();
+ Size size = new Size();
+
+ // get the max position of the first quarter of the screen
+ pos.x = screenDim.width / 2;
+ pos.y = screenDim.height / 2;
+ windowMaxPosition = pos;
+
+ // get the max size of the windows while they placed in windowMaxPosition
+ // range and not outside the visibility
+ size.Height = screenDim.height;
+ size.Width = screenDim.width;
+ windowMaxSize = size;
+ }
+
+ private void generateDesktop(){
+
+ // create some documents with content
+ makeWriterDoc("WriterDoc1", true);
+// makeCalcDoc("CalcDoc1", true);
+// makeDrawDoc("DrawDoc1", true);
+// makeImpressDoc("ImpressDoc1", true);
+// makeMathDoc("MathDoc1", true);
+
+ // create some documents without content
+// makeMathDoc("_blank_math", false);
+// makeDrawDoc("_blank_draw", false);
+// makeCalcDoc("_blank_calc", false);
+// makeWriterDoc("_blank_writer", false);
+// makeImpressDoc("_blank_impress", false);
+
+// makeMathDoc("MathDocEmpty", false);
+// makeDrawDoc("DrawDocEmpty", false);
+// makeCalcDoc("CalcDocEmpty", false);
+ makeWriterDoc("WriterDocEmpty", false);
+// makeImpressDoc("ImpressDocEmpty", false);
+
+ log.println("Test object successfully created.");
+
+ }
+
+ private void makeImpressDoc(String frameName, boolean withContent){
+ log.println("creating Impress document '" + frameName + "'");
+ XComponent xImpressDoc = createNewImpressDoc(frameName);
+ if (withContent) fillImpressDocWithContent(xImpressDoc);
+ positioningDocument((XModel) UnoRuntime.queryInterface(XModel.class,
+ xImpressDoc));
+ }
+
+ private void makeDrawDoc(String frameName, boolean withContent){
+ log.println("creating Draw document '" + frameName + "'");
+ XComponent xDrawDoc = createNewDrawDoc(frameName);
+ if (withContent) fillDrawDocWithContent(xDrawDoc);
+ positioningDocument((XModel) UnoRuntime.queryInterface(XModel.class,
+ xDrawDoc));
+ }
+
+ private void makeCalcDoc(String frameName, boolean withContent){
+ log.println("creating Calc document '" + frameName + "'");
+ XSpreadsheetDocument xSpreadsheetDoc = createNewCalcDoc(frameName);
+ if (withContent) fillCalcDocWithContent(xSpreadsheetDoc);
+ positioningDocument((XModel) UnoRuntime.queryInterface(XModel.class,
+ xSpreadsheetDoc));
+ }
+
+ private void positioningDocument(XModel model){
+
+ XWindow xWindow = model.getCurrentController().getFrame().getContainerWindow();
+ String frameName = model.getCurrentController().getFrame().getName();
+
+ // get randomized position and size
+ Rectangle posSize = makePosZize();
+
+ // save position and size
+ windowsPosSize.put(frameName, posSize);
+
+ xWindow.setPosSize(posSize.X, posSize.Y, posSize.Width, posSize.Height,
+ com.sun.star.awt.PosSize.POSSIZE);
+ Rectangle test = xWindow.getPosSize();
+ log.println("x: "+test.X+" y:"+test.Y+" width:"+test.Width+" height:"+test.Height);
+ }
+
+ private Rectangle makePosZize(){
+
+ Rectangle posSize = new Rectangle();
+ Random rand = new Random();
+
+ // Random integers that range from from 0 to n
+ posSize.X = rand.nextInt(windowMaxPosition.x + 1);
+ posSize.Y = rand.nextInt(windowMaxPosition.y + 1);
+
+ int maxHeight = windowMaxSize.Height-posSize.X;
+ int maxWidth = windowMaxSize.Width-posSize.Y;
+ int height = rand.nextInt(maxHeight + 1);
+ int width = rand.nextInt((windowMaxSize.Width-posSize.Y) + 1);
+
+ // be shure that the new size his greater then the half of windowMaxSize
+ posSize.Height = (height < (maxHeight / 2)) ? height + (maxHeight / 2) : height;
+ posSize.Width = (width < (maxWidth / 2)) ? width + (maxWidth / 2) : width;
+
+ return posSize;
+ }
+
+ private void makeMathDoc(String frameName, boolean withContent){
+ log.println("creating Math document '" + frameName + "'");
+ XComponent xMathDoc = createNewMathDoc(frameName);
+ if (withContent) fillMathDocWithContent(xMathDoc);
+ positioningDocument((XModel) UnoRuntime.queryInterface(XModel.class,
+ xMathDoc));
+ }
+
+ private XComponent createNewMathDoc(String frameName){
+ XComponent xMathDoc = null;
+ try{
+ xMathDoc = SOF.createMathDoc(frameName);
+ } catch (com.sun.star.uno.Exception e) {
+ log.println("Exception occured while creating math document '"+frameName+"':");
+ failed("Couldn't create test environment");
+ }
+ return xMathDoc;
+ }
+
+ private void fillMathDocWithContent(XComponent xMathDoc){
+ // setting a formula in document
+ final String expFormula = "sum a cdot b";
+ final XPropertySet xPS = (XPropertySet) UnoRuntime.queryInterface
+ (XPropertySet.class, xMathDoc);
+ try {
+ xPS.setPropertyValue("Formula", expFormula);
+ } catch(com.sun.star.lang.WrappedTargetException e) {
+ log.println("Exception occured while filling math document with content.");
+ failed("Couldn't create test environment");
+ } catch(com.sun.star.lang.IllegalArgumentException e) {
+ log.println("Exception occured while filling math document with content.");
+ failed("Couldn't create test environment");
+ } catch(com.sun.star.beans.PropertyVetoException e) {
+ log.println("Exception occured while filling math document with content.");
+ failed("Couldn't create test environment");
+ } catch(com.sun.star.beans.UnknownPropertyException e) {
+ log.println("Exception occured while filling math document with content.");
+ failed("Couldn't create test environment");
+ }
+ }
+
+ private XComponent createNewImpressDoc(String frameName){
+ XComponent xImpressDoc = null;
+ try{
+ xImpressDoc = SOF.createImpressDoc(frameName);
+ } catch (com.sun.star.uno.Exception e) {
+ log.println("Exception occured while creating impress document '"+frameName+"':");
+ failed("Couldn't create test environment");
+ }
+ return xImpressDoc;
+ }
+
+
+ private void fillImpressDocWithContent(XComponent xImpressDoc){
+
+ log.println( "get presentation" );
+ XPresentationSupplier oPS = (XPresentationSupplier)
+ UnoRuntime.queryInterface(XPresentationSupplier.class, xImpressDoc);
+ XInterface oObj = oPS.getPresentation();
+
+ log.println( "get custom presentation" );
+ XCustomPresentationSupplier oCPS = (XCustomPresentationSupplier)
+ UnoRuntime.queryInterface(
+ XCustomPresentationSupplier.class, xImpressDoc);
+ XNameContainer xCP = oCPS.getCustomPresentations();
+
+ XInterface oInstance = null;
+
+ XSingleServiceFactory oSingleMSF = (XSingleServiceFactory)
+ UnoRuntime.queryInterface(XSingleServiceFactory.class, xCP);
+
+ try{
+ oInstance = (XInterface) oSingleMSF.createInstance();
+ } catch (com.sun.star.uno.Exception e) {
+ log.println("Could not create custom presentation while filling impress document with content.");
+ failed("Couldn't create test environment");
+ }
+
+ try {
+ xCP.insertByName("FirstPresentation",oInstance);
+ } catch (com.sun.star.lang.WrappedTargetException e) {
+ log.println("Could not instert custom presentation while filling impress document with content.");
+ failed("Couldn't create test environment");
+ } catch (com.sun.star.container.ElementExistException e) {
+ log.println("Could not instert custom presentation while filling impress document with content.");
+ failed("Couldn't create test environment");
+ } catch (com.sun.star.lang.IllegalArgumentException e) {
+ log.println("Could not instert custom presentation while filling impress document with content.");
+ failed("Couldn't create test environment");
+ }
+ }
+
+ private XComponent createNewDrawDoc(String frameName){
+ XComponent xDrawDoc = null;
+ try{
+ xDrawDoc = SOF.createDrawDoc(frameName);
+ } catch (com.sun.star.uno.Exception e) {
+ log.println("Exception occured while creating draw document '"+frameName+"':");
+ failed("Couldn't create test environment");
+ }
+ return xDrawDoc;
+ }
+
+ private void fillDrawDocWithContent(XComponent xDrawDoc){
+ XDrawPagesSupplier oDPS = (XDrawPagesSupplier)
+ UnoRuntime.queryInterface(XDrawPagesSupplier.class, xDrawDoc);
+ XDrawPages oDPn = oDPS.getDrawPages();
+ XIndexAccess oDPi = (XIndexAccess)
+ UnoRuntime.queryInterface(XIndexAccess.class, oDPn);
+ XDrawPage oDP = null;
+ try {
+ oDP = (XDrawPage) AnyConverter.toObject(
+ new Type(XDrawPage.class),oDPi.getByIndex(0));
+ } catch (com.sun.star.lang.WrappedTargetException e) {
+ log.println("Could not get draw pages while filling draw document with content.");
+ failed("Couldn't create test environment");
+ } catch (com.sun.star.lang.IndexOutOfBoundsException e) {
+ log.println("Could not get draw pages while filling draw document with content.");
+ failed("Couldn't create test environment");
+ } catch (com.sun.star.lang.IllegalArgumentException e) {
+ log.println("Could not get draw pages while filling draw document with content.");
+ failed("Couldn't create test environment");
+ }
+
+ //get a Shape
+ log.println( "getting Shape" );
+ XShapes oShapes = (XShapes) UnoRuntime.queryInterface
+ (XShapes.class, oDP);
+ XInterface oObj = SOF.createShape
+ (xDrawDoc, 5000, 3500, 7500, 5000, "Rectangle");
+ for (int i=0; i < 10; i++) {
+ oShapes.add(
+ SOF.createShape(xDrawDoc,
+ 5000, 3500, 7510 + 10 * i, 5010 + 10 * i, "Rectangle"));
+ }
+ XShape oShape = SOF.createShape
+ (xDrawDoc, 3000, 4500, 15000, 1000, "Ellipse");
+ oShapes.add((XShape) oObj);
+ oShapes.add((XShape) oShape);
+
+
+ XPropertySet oShapeProps = (XPropertySet)
+ UnoRuntime.queryInterface(XPropertySet.class, oObj);
+ XStyle aStyle = null;
+ try {
+ aStyle = (XStyle) AnyConverter.toObject(
+ new Type(XStyle.class),oShapeProps.getPropertyValue("Style"));
+ oShapeProps.setPropertyValue("ZOrder", new Integer(1));
+ } catch (com.sun.star.lang.WrappedTargetException e) {
+ log.println("Exception occured while setting or getting property value while filling draw document with content.");
+ failed("Couldn't create test environment");
+ } catch (com.sun.star.beans.UnknownPropertyException e) {
+ log.println("Exception occured while setting or getting property value while filling draw document with content.");
+ failed("Couldn't create test environment");
+ } catch (com.sun.star.lang.IllegalArgumentException e) {
+ log.println("Exception occured while setting or getting property value while filling draw document with content.");
+ failed("Couldn't create test environment");
+ } catch (com.sun.star.beans.PropertyVetoException e) {
+ log.println("Exception occured while setting or getting property value while filling draw document with content.");
+ failed("Couldn't create test environment");
+ }
+ }
+
+ private void makeWriterDoc(String frameName, boolean withContent){
+ log.println("creating Writer document '" + frameName + "'");
+ XTextDocument xTextDoc = createNewWriterDoc(frameName);
+ if (withContent) fillWriterDocWithContent(xTextDoc);
+ positioningDocument((XModel) UnoRuntime.queryInterface(XModel.class,
+ xTextDoc));
+ }
+
+ private XTextDocument createNewWriterDoc(String frameName){
+ XTextDocument xTextDoc = null;
+ try {
+ xTextDoc = SOF.createTextDoc(frameName);
+ } catch (com.sun.star.uno.Exception e) {
+ log.println("Exception occured while creating text document '"+frameName+"':");
+ failed("Couldn't create test environment");
+ }
+ return xTextDoc;
+ }
+
+ private void fillWriterDocWithContent(XTextDocument xTextDoc){
+ try{
+ log.println( "inserting some lines" );
+ XText oText = xTextDoc.getText();
+ XTextCursor oCursor = oText.createTextCursor();
+ for (int i=0; i<5; i++){
+ oText.insertString( oCursor,"Paragraph Number: " + i, false);
+ oText.insertString( oCursor,
+ " The quick brown fox jumps over the lazy Dog: SwXParagraph",
+ false);
+ oText.insertControlCharacter(
+ oCursor, ControlCharacter.PARAGRAPH_BREAK, false );
+ oText.insertString( oCursor,
+ "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG: SwXParagraph",
+ false);
+ oText.insertControlCharacter(oCursor,
+ ControlCharacter.PARAGRAPH_BREAK, false );
+ oText.insertControlCharacter(
+ oCursor, ControlCharacter.LINE_BREAK, false );
+ }
+ } catch ( com.sun.star.lang.IllegalArgumentException e ){
+ log.println("Exception occured while filling text document with content.");
+ failed("Couldn't create test environment");
+ } catch (com.sun.star.uno.Exception e) {
+ log.println("Exception occured while filling text document with content.");
+ failed("Couldn't create test environment");
+ }
+ }
+
+ private XSpreadsheetDocument createNewCalcDoc(String frameName){
+
+ XSpreadsheetDocument xSheetDoc = null;
+
+ try {
+ xSheetDoc = SOF.createCalcDoc(frameName);
+ } catch (com.sun.star.uno.Exception e) {
+ log.println("Exception occured while creating calc document '"+frameName+"':");
+ failed("Couldn't create test environment");
+ }
+ return xSheetDoc;
+ }
+
+ private void fillCalcDocWithContent(XSpreadsheetDocument xSpreadsheetDoc){
+
+ try{
+ XSpreadsheets oSpreadsheets = xSpreadsheetDoc.getSheets();
+
+ XSpreadsheet oSheet = (XSpreadsheet) AnyConverter.toObject(
+ new Type(XSpreadsheet.class),
+ oSpreadsheets.getByName(
+ oSpreadsheets.getElementNames()[0]));
+
+ XCellRange testRange = oSheet.getCellRangeByName("$A$1:$D$4");
+
+ XSheetCellRange testSheetRange = (XSheetCellRange) UnoRuntime.queryInterface(
+ XSheetCellRange.class,
+ testRange);
+ oSheet.getCellByPosition(1, 1).setValue(1);
+ oSheet.getCellByPosition(4, 5).setValue(1);
+ oSheet.getCellByPosition(3, 2).setFormula("xTextDoc");
+ oSheet.getCellByPosition(3, 3).setFormula("xTextDoc");
+ } catch (com.sun.star.lang.WrappedTargetException e) {
+ log.println("Exception occured while filling calc document with content.");
+ failed("Couldn't create test environment");
+ } catch (com.sun.star.container.NoSuchElementException e) {
+ log.println("Exception occured while filling calc document with content.");
+ failed("Couldn't create test environment");
+ } catch (com.sun.star.lang.IndexOutOfBoundsException e) {
+ log.println("Exception occured while filling calc document with content.");
+ failed("Couldn't create test environment");
+ } catch (com.sun.star.lang.IllegalArgumentException e) {
+ log.println("Exception occured while filling calc document with content.");
+ failed("Couldn't create test environment");
+ } catch (com.sun.star.uno.Exception e) {
+ log.println("Exception occured while filling calc document with content.");
+ failed("Couldn't create test environment");
+ }
+ }
+
+ /**
+ * copies all files from the backup folder into a folder called backup.recoveryTest
+ * and copies the Recovery.xcu to recovery.xcu.recoeryTest
+ */
+ private void backupRecoveryData()
+ {
+ log.println("backup recovery data...");
+ try{
+ rt.copyRecoveryData(true);
+ }catch (com.sun.star.io.IOException e){
+ failed("could not copy recovery data: " + e.toString());
+ }catch (java.io.IOException e){
+ failed("could not copy recovery data: " + e.toString());
+ }
+ }
+
+ /**
+ * copies all files from the backup.recoveryTest folder into the backup folder
+ * and copies the Recovery.xcu.recoveryTest to recovery.xcu
+ */
+ private void restoreBackupRecoveryData()
+ {
+ log.println("restore backup recovery data...");
+ try{
+ rt.copyRecoveryData(false);
+ }catch (com.sun.star.io.IOException e){
+ failed("could not copy recovery data: " + e.toString());
+ }catch (java.io.IOException e){
+ failed("could not copy recovery data: " + e.toString());
+ }
+ }
+
+ private void cleanRecoveryData(){
+ try{
+ log.println("bootstrapping the office to get user path to remove old recovery data...");
+
+ rt.cleanRecoveryData();
+
+ } catch (com.sun.star.io.IOException e){
+ failed("could not clean recovery data: " + e.toString());
+ }
+ }
+}
diff --git a/framework/qa/complex/framework/recovery/RecoveryTools.java b/framework/qa/complex/framework/recovery/RecoveryTools.java
new file mode 100644
index 000000000000..28936949d8ef
--- /dev/null
+++ b/framework/qa/complex/framework/recovery/RecoveryTools.java
@@ -0,0 +1,366 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package complex.framework.recovery;
+
+import com.sun.star.awt.XDialog;
+import com.sun.star.awt.XExtendedToolkit;
+import com.sun.star.awt.XWindow;
+import com.sun.star.beans.NamedValue;
+import com.sun.star.frame.XController;
+import com.sun.star.frame.XDesktop;
+import com.sun.star.frame.XDispatch;
+import com.sun.star.frame.XDispatchProvider;
+import com.sun.star.frame.XModel;
+import com.sun.star.lang.XComponent;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.ucb.XSimpleFileAccess;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.XInterface;
+import com.sun.star.util.URL;
+import com.sun.star.util.XURLTransformer;
+import helper.FileTools;
+import helper.OfficeProvider;
+import helper.UnoProvider;
+import java.io.File;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import lib.TestParameters;
+import share.LogWriter;
+import util.PropertyName;
+import util.UITools;
+import util.utils;
+
+/**
+ * this class supports the <CODE>RecoverTest</CODE>. You will find here some helper
+ * functions.
+ */
+public class RecoveryTools {
+
+ private final TestParameters param;
+ private final LogWriter log;
+
+ /**
+ * Creates new OfficeWatcher
+ * @param param the test parameter
+ * @param log a log writer
+ */
+ public RecoveryTools(TestParameters param, LogWriter log) {
+ this.param = param;
+ this.log = log;
+
+ }
+
+ /**
+ * get the active dialog from the top of the desktop
+ * @param xToolKit xToolKit the <CODE> XExtendedToolkit</CODE> to get the dialog from the top of the desktop.
+ * @return a <CODE>XDialog</CODE> interface of the dialog
+ */
+ public XDialog getActiveDialog( XMultiServiceFactory xMSF){
+ XWindow xWin = getActiveWindow(xMSF);
+ return (XDialog) UnoRuntime.queryInterface(XDialog.class, xWin);
+ }
+
+ public XWindow getActiveWindow( XMultiServiceFactory xMSF){
+ XInterface xToolKit = null;
+ try {
+ xToolKit = (XInterface) xMSF.createInstance("com.sun.star.awt.Toolkit") ;
+ } catch (com.sun.star.uno.Exception e) {
+ return null;
+ }
+
+ XExtendedToolkit tk = (XExtendedToolkit)
+ UnoRuntime.queryInterface(XExtendedToolkit.class, xToolKit);
+ Object atw = tk.getActiveTopWindow();
+ return (XWindow) UnoRuntime.queryInterface(XWindow.class, atw);
+ }
+
+ /**
+ * After a crash the office start with a recovery diaolg. It could be that the office
+ * is connectable but not all services to get the dialog a loaded. This function
+ * tries to get the dialog until the <CODE>OfficeWatcher</CODE> kills the office.
+ * @param xToolKit the <CODE> XExtendedToolkit</CODE> to get the dialog from the top of the desktop.
+ * @return a <CODE>XDialog</CODE> interface of the dialog
+ */
+ public XDialog getActiveDialogAfterStartup(XMultiServiceFactory xMSF){
+ // while the office starts it takes some time to get the dialog.
+
+ // the dialog is accessible AFTER the office has recoverd all documents.
+ // This could consumes more time then the TimeOut allow.
+ int counter = 0;
+ int multi = 5;
+ int pause = param.getInt(PropertyName.SHORT_WAIT)*10;
+ int timeOut = param.getInt(PropertyName.THREAD_TIME_OUT)*5;
+ int maximum = (timeOut / pause) * multi;
+
+ XDialog oDialog = getActiveDialog(xMSF);
+
+ while (oDialog == null && (counter < maximum)){
+ log.println("waiting until the office has recoverd... remaining " + (timeOut * multi - pause * counter)/1000 + " seconds");
+ pause(pause);
+ oDialog = getActiveDialog(xMSF);
+ counter ++;
+ }
+ return oDialog;
+ }
+
+ /**
+ * halt the thread for some time
+ */
+ public void pause(){
+ pause(param.getInt(PropertyName.SHORT_WAIT));
+ }
+
+ /**
+ * halt the thread for some time
+ */
+ public void pause(int sleepTime){
+ sleep(sleepTime);
+ }
+
+ private void sleep(long millis){
+ try{
+ Thread.sleep(millis);
+ }catch (java.lang.InterruptedException e){}
+ }
+
+ /**
+ * remove the content of the user backup folder and removes the Recovery.xcu. This
+ * was done from the Office via XSimpleFileAccess
+ * @param xMSF a <CODE>XMultiServiceFactory</CODE> to get <CODE>XSimpleFileAccess</CODE>
+ * @throws com.sun.star.io.IOException the exception was thrown if something goes wrong.
+ */
+ public void cleanRecoveryData()
+ throws com.sun.star.io.IOException
+ {
+ try{
+ HashMap recFiles = getRecoveryFiles();
+
+ String recoveryFolder = (String) recFiles.get("recoveryFolder");
+ String recoveryXCU = (String) recFiles.get("recoveryXCU");
+
+ log.println("try to remove content of '" + recoveryFolder + "'");
+
+ File rf = new File(recoveryFolder);
+
+ boolean success = FileTools.cleanDir(rf);
+ log.println("removed " + recoveryFolder + ": " + success);
+
+ log.println("try to remove '" + recoveryXCU + "'");
+
+ File xcu = new File(recoveryXCU);
+ if (xcu.isFile()){
+ success = xcu.delete();
+ log.println("removed " + recoveryXCU + " : " + success);
+ }
+
+ } catch (Exception e){
+ throw new com.sun.star.io.IOException("could not remove old recovery data: " + e.toString());
+ }
+ }
+
+ public HashMap getRecoveryFiles()
+ throws com.sun.star.io.IOException
+ {
+ try{
+ log.println("try to get UnoProvider...");
+ UnoProvider unoProv = new UnoProvider();
+ XMultiServiceFactory xMSF = (XMultiServiceFactory) unoProv.getManager(param);
+
+ String userPath = utils.expandMacro(xMSF, "${$ORIGIN/bootstraprc:UserInstallation}");
+ System.out.println("userPath:'" + userPath + "'");
+
+ if (userPath.equals(""))userPath = utils.expandMacro(xMSF, "${$ORIGIN/bootstrap.ini:UserInstallation}");
+ System.out.println("userPath:'" + userPath + "'");
+
+ if (userPath.equals("")) throw new com.sun.star.io.IOException("could not get user path at bootstraping");
+
+ String recoveryFolder = utils.getSystemURL(userPath + "/user/backup");
+
+ String recoveryXCU = utils.getSystemURL(userPath + "/user/registry/data/org/openoffice/Office/Recovery.xcu");
+
+ HashMap recFiles = new HashMap();
+
+ recFiles.put("recoveryFolder", recoveryFolder);
+ recFiles.put("recoveryXCU", recoveryXCU);
+ return recFiles;
+
+ } catch (Exception e){
+ throw new com.sun.star.io.IOException("could not get recovery folder: " + e.toString());
+ }
+
+ }
+ /**
+ * This function close the office while calling terminate on the desktop. If
+ * this failed, the <CODE>ProcessHandler</CODE> kills the process.
+ * @param xMSF the <CODE>XMultiServiceFactory</CODE>
+ * @return <CODE>TRUE</CODE> if no exception was thrown, otherwise <CODE>FALSE</CODE>
+ */
+ public boolean closeOffice(XMultiServiceFactory xMSF) {
+ try {
+ XDesktop desk = (XDesktop) UnoRuntime.queryInterface(
+ XDesktop.class, xMSF.createInstance(
+ "com.sun.star.frame.Desktop"));
+ xMSF = null;
+
+ desk.terminate();
+ log.println("Waiting until ProcessHandler loose the office...");
+
+ }
+ catch (java.lang.Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+ waitForClosedOffice();
+ return true;
+ }
+
+ /**
+ * This function waits until the office is closed. If the closing time reach
+ * the value of parameter <CODE>THREAD_TIME_OUT</CODE> the office was killed.
+ */
+ public void waitForClosedOffice(){
+ // check for the office process
+ helper.ProcessHandler ph = (helper.ProcessHandler) param.get("AppProvider");
+
+ int timeOut = param.getInt(PropertyName.THREAD_TIME_OUT)*5;
+ int pause = param.getInt(PropertyName.SHORT_WAIT)*20;
+ int multi = 0;
+ while ((ph != null) && (ph.getExitCode()<0) && (pause*multi < timeOut)) {
+ log.println("waiting until the office is closed... remaining " + (timeOut - pause * multi)/1000 + " seconds");
+ pause(pause);
+ multi ++;
+ }
+
+ // be shure that office is closed
+ if (ph != null) ph.kill();
+ }
+
+ public void killOffice(){
+ helper.ProcessHandler ph = (helper.ProcessHandler) param.get("AppProvider");
+ ph.kill();
+ }
+
+ /**
+ * The office must be started WITH restore and crashreporter functionality.
+ * Therefore the parmater '<CODE>-norestore</CODE>' and '<CODE>-nocrashreport</CODE>'
+ * was removed from the <CODE>AppExecutionCommand</CODE> parameter
+ */
+ public void removeParametersFromAppExecutionCommand(){
+
+ //remove some params to start office
+ String office = (String) param.get("AppExecutionCommand");
+ String[] params = {"-norestore", "-nocrashreport"};
+
+ for (int i = 0; i < params.length; i++){
+ int index = office.indexOf(params[i]);
+ int length = params[i].length();
+ if (index != -1){
+ office = office.substring(0, index) + office.substring(index + length);
+ log.println("removed '" + params[i] + "' from AppExecutionCommand: " + office);
+ }
+ }
+ param.put("AppExecutionCommand", office);
+ log.println("connect: " + (String) param.get("AppExecutionCommand"));
+
+ }
+
+ /**
+ * This function uses accessibility to handle modal dialogs like the
+ * "Are you sure" dialog.
+ * It cklick the named button given in parameter <CODE>buttonName</CODE>
+ * @param buttonName the name of the button wich should be chlicked
+ */
+ public void handleModalDialog(XMultiServiceFactory xMSF, String buttonName)
+ throws com.sun.star.accessibility.IllegalAccessibleComponentStateException
+ {
+
+ log.println("try to get modal Dialog...");
+
+ pause();
+
+ XWindow oDialog = getActiveWindow(xMSF);
+
+ if (oDialog == null) throw new com.sun.star.accessibility.IllegalAccessibleComponentStateException("could not get modal Dialog");
+
+
+ UITools oUITools = new UITools(xMSF, oDialog);
+ oUITools.printAccessibleTree((PrintWriter) log, param.getBool(PropertyName.DEBUG_IS_ACTIVE));
+
+ try{
+ log.println("click ' " + buttonName + "' button..");
+ oUITools.clickButton(buttonName);
+ } catch ( java.lang.Exception e){
+ throw new com.sun.star.accessibility.IllegalAccessibleComponentStateException("Could not klick '"+buttonName +"' at modal dialog: " + e.toString());
+ }
+ pause();
+ }
+
+ public void clickThreadButton(XMultiServiceFactory xMSF, XWindow xWindow, String buttonName)
+ throws com.sun.star.accessibility.IllegalAccessibleComponentStateException
+ {
+ KlickButtonThread kbt = new KlickButtonThread(xMSF, xWindow, buttonName);
+ kbt.start();
+ pause(param.getInt(PropertyName.SHORT_WAIT) * 10);
+ }
+
+ public void copyRecoveryData(boolean backup)
+ throws com.sun.star.io.IOException, java.io.IOException
+ {
+ HashMap recFiles = null;
+
+ try{
+ recFiles = getRecoveryFiles();
+ } catch ( com.sun.star.io.IOException e){
+ throw new com.sun.star.io.IOException("Could not get recovery files: " + e.toString());
+ }
+
+ try{
+ String recoveryFolder = (String) recFiles.get("recoveryFolder");
+ String recoveryXCU = (String) recFiles.get("recoveryXCU");
+
+ File recFolder = new File(recoveryFolder);
+ File recFolderBackup = new File(recoveryFolder+".recoveryTest");
+
+ File recXCU = new File(recoveryXCU);
+ File recXCUBackup = new File(recoveryXCU + ".recoveryTest");
+
+ if (backup){
+ FileTools.copyDirectory(recFolder, recFolderBackup);
+ FileTools.copyFile(recXCU, recXCUBackup);
+ } else {
+ FileTools.copyDirectory(recFolderBackup, recFolder);
+ FileTools.copyFile(recXCUBackup, recXCU);
+
+ }
+ } catch (java.io.IOException e){
+ throw new java.io.IOException("Could not copy recovery files: " + e.toString());
+ }
+ }
+
+
+} \ No newline at end of file
diff --git a/framework/qa/complex/framework/recovery/TimeoutThread.java b/framework/qa/complex/framework/recovery/TimeoutThread.java
new file mode 100644
index 000000000000..088f4b3d36f6
--- /dev/null
+++ b/framework/qa/complex/framework/recovery/TimeoutThread.java
@@ -0,0 +1,41 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package complex.framework.recovery;
+
+public class TimeoutThread extends Thread{
+ public int timeOut = 0;
+ /** Creates a new instance of TimeoutThread */
+ public TimeoutThread(int timeOut) {
+ this.timeOut = timeOut;
+ }
+
+ public void run(){
+ util.utils.shortWait(timeOut);
+ }
+
+}
diff --git a/framework/qa/complex/framework/recovery/makefile.mk b/framework/qa/complex/framework/recovery/makefile.mk
new file mode 100755
index 000000000000..4a9f80b4b2a5
--- /dev/null
+++ b/framework/qa/complex/framework/recovery/makefile.mk
@@ -0,0 +1,103 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org 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 Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ = ..$/..$/..$/..
+TARGET = RecoveryTest
+PRJNAME = framework
+PACKAGE = complex$/framework$/recovery
+
+# --- Settings -----------------------------------------------------
+.INCLUDE: settings.mk
+
+
+#----- compile .java files -----------------------------------------
+
+JARFILES = mysql.jar mysql.jar ridl.jar unoil.jar jurt.jar juh.jar java_uno.jar OOoRunner.jar
+JAVAFILES = RecoveryTest.java RecoveryTools.java CrashThread.java TimeoutThread.java KlickButtonThread.java
+JAVACLASSFILES = $(foreach,i,$(JAVAFILES) $(CLASSDIR)$/$(PACKAGE)$/$(i:b).class)
+
+#----- make a jar from compiled files ------------------------------
+
+MAXLINELENGTH = 100000
+
+JARCLASSDIRS = $(PACKAGE)
+JARTARGET = $(TARGET).jar
+JARCOMPRESS = TRUE
+
+#------ some information how to run the test -----------------------
+
+MYTAR: ALLTAR
+ @echo
+ @echo ########################### N O T E ######################################
+ @echo
+ @echo To run the test successfully you have to extend your LD_LIBRARY_PATH
+ @echo to your office program directory!
+ @echo Example:
+ @echo setenv LD_LIBRARY_PATH /myOffice/program:\$$LD_LIBRARY_PATH
+ @echo
+ @echo To run the you have to use the parameter cmd:
+ @echo cmd="PATH_TO_OFFICE_BINARY -accept=socket,host=localhost,port=8100;urp;"
+ @echo
+ @echo Example:
+ @echo dmake run cmd="/myOffice/program/soffice -accept=socket,host=localhost,port=8100;urp;"
+ @echo
+
+
+# --- Parameters for the test --------------------------------------
+
+# start an office if the parameter is set for the makefile
+.IF "$(cmd)" == ""
+CT_APPEXECCOMMAND =
+.ELSE
+CT_APPEXECCOMMAND = -cmd "$(cmd)"
+#CT_APPEXECCOMMAND = -AppExecutionCommand \
+# "$(OFFICE)$/soffice -accept=socket,host=localhost,port=8100;urp;"
+.ENDIF
+
+# test base is java complex
+CT_TESTBASE = -TestBase java_complex
+
+# replace $/ with . in package name
+CT_PACKAGE = -o $(PACKAGE:s\$/\.\)
+
+# start the runner application
+CT_APP = org.openoffice.Runner
+
+CT_NOOFFICE = -NoOffice true
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+
+RUN: run
+# muss noch angepasst werden: es soll auf -AppExecutionCommand und -NoOffice gepr??ft werden
+#.IF "$(OFFICE)" == ""
+#run:
+# @echo Exit
+#.ELSE
+run:
+ +java -cp $(CLASSPATH) $(CT_APP) $(CT_TESTBASE) $(CT_APPEXECCOMMAND) $(CT_NOOFFICE) $(CT_PACKAGE).RecoveryTest
+