summaryrefslogtreecommitdiffstats
path: root/qadevOOo/runner/helper
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
commit940b4d1848e8c70ab7642901a68594e8016caffc (patch)
treeeb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /qadevOOo/runner/helper
parentInitial commit. (diff)
downloadlibreoffice-upstream/1%7.0.4.tar.xz
libreoffice-upstream/1%7.0.4.zip
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--qadevOOo/runner/helper/APIDescGetter.java970
-rw-r--r--qadevOOo/runner/helper/AppProvider.java48
-rw-r--r--qadevOOo/runner/helper/CfgParser.java124
-rw-r--r--qadevOOo/runner/helper/ClParser.java137
-rw-r--r--qadevOOo/runner/helper/ComplexDescGetter.java183
-rw-r--r--qadevOOo/runner/helper/ConfigHelper.java303
-rw-r--r--qadevOOo/runner/helper/ConfigurationRead.java82
-rw-r--r--qadevOOo/runner/helper/ContextMenuInterceptor.java131
-rw-r--r--qadevOOo/runner/helper/FileTools.java127
-rw-r--r--qadevOOo/runner/helper/LoggingThread.java80
-rw-r--r--qadevOOo/runner/helper/OSHelper.java50
-rw-r--r--qadevOOo/runner/helper/OfficeProvider.java756
-rw-r--r--qadevOOo/runner/helper/OfficeWatcher.java93
-rw-r--r--qadevOOo/runner/helper/ProcessHandler.java400
-rw-r--r--qadevOOo/runner/helper/PropertyHandlerFactroy.java35
-rw-r--r--qadevOOo/runner/helper/PropertyHandlerImpl.java234
-rw-r--r--qadevOOo/runner/helper/StreamSimulator.java394
-rw-r--r--qadevOOo/runner/helper/StringHelper.java64
-rw-r--r--qadevOOo/runner/helper/URLHelper.java151
-rw-r--r--qadevOOo/runner/helper/UnoProvider.java141
20 files changed, 4503 insertions, 0 deletions
diff --git a/qadevOOo/runner/helper/APIDescGetter.java b/qadevOOo/runner/helper/APIDescGetter.java
new file mode 100644
index 000000000..65f8da05c
--- /dev/null
+++ b/qadevOOo/runner/helper/APIDescGetter.java
@@ -0,0 +1,970 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package helper;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.StringTokenizer;
+import java.util.jar.JarEntry;
+
+import share.DescEntry;
+import share.DescGetter;
+
+/**
+ * This is the Office-API specific DescGetter<br>
+ * <br>
+ * Examples:<br><br>
+ * -o sw.SwXBodyText<br>
+ * runs the module test of <B>Sw.SwXBodyText</B><br>
+ * <br>
+ * -o sw.SwXBodyText::com::sun::star::text::Text<br>
+ * runs only the interface test <B>com.sun.star.textText</B> of the module <B>Sw.SwXBodyText</B><br>
+ * <br>
+ * -o sw.SwXBodyText::com::sun::star::text::Text,com::sun::star::text::XSimpleText<br>
+ * runs only the interfaces test <B>com.sun.star.textText</B> and <B>com.sun.star.text.XSimpleText</B> of the module <B>Sw.SwXBodyText</B><br>
+ * <br>
+ * -p sw<br>
+ * runs all modules of the project <B>sw</B><br>
+ * <br>
+ * -p listall<br>
+ * lists all known module tests<br>
+ * <br>
+ * -sce SCENARIO_FILE<br>
+ * A scenario file is a property file which could contain <B>-o</B> and <B>-p</B> properties<br>
+ * <br>
+ * -sce sw.SwXBodyText,sw.SwXBookmark<br>
+ * runs the module test of <B>Sw.SwXBodyText</B> and <B>sw.SwXBookmark</B><br>
+ */
+public class APIDescGetter extends DescGetter
+{
+
+ private static String fullJob = null;
+
+ /*
+ * gets the needed information about a StarOffice component
+ * @param descPath Path to the ComponentDescription
+ * @param entry contains the entry name, e.g. sw.SwXBodyText
+ * @param debug if true some debug information is displayed on standard out
+ */
+ @Override
+ public DescEntry[] getDescriptionFor(String job, String descPath,
+ boolean debug)
+ {
+
+ if (job.startsWith("-o"))
+ {
+ job = job.substring(3, job.length()).trim();
+
+ if (job.indexOf('.') < 0)
+ {
+ return null;
+ }
+
+ // special in case several Interfaces are given comma separated
+ if (job.indexOf(',') < 0)
+ {
+ DescEntry entry = getDescriptionForSingleJob(job, descPath,
+ debug);
+
+ if (entry != null)
+ {
+ return new DescEntry[]
+ {
+ entry
+ };
+ }
+ else
+ {
+ return null;
+ }
+ }
+ else
+ {
+ ArrayList<String> subs = getSubInterfaces(job);
+ String partjob = job.substring(0, job.indexOf(',')).trim();
+ DescEntry entry = getDescriptionForSingleJob(partjob, descPath,
+ debug);
+
+ if (entry != null)
+ {
+ for (int i = 0; i < entry.SubEntryCount; i++)
+ {
+ String subEntry = entry.SubEntries[i].longName;
+ int cpLength = entry.longName.length();
+ subEntry = subEntry.substring(cpLength + 2,
+ subEntry.length());
+
+ if (subs.contains(subEntry))
+ {
+ entry.SubEntries[i].isToTest = true;
+ }
+ }
+
+ return new DescEntry[]
+ {
+ entry
+ };
+ }
+ else
+ {
+ return null;
+ }
+ }
+ }
+
+ if (job.startsWith("-p"))
+ {
+ job = job.substring(3, job.length()).trim();
+
+ String[] scenario = createScenario(descPath, job, debug);
+ if (scenario == null)
+ {
+ return null;
+ }
+ DescEntry[] entries = new DescEntry[scenario.length];
+ for (int i = 0; i < scenario.length; i++)
+ {
+ entries[i] = getDescriptionForSingleJob(
+ scenario[i].substring(3).trim(), descPath, debug);
+ }
+ if (job.equals("listall"))
+ {
+ util.dbg.printArray(scenario);
+ System.exit(0);
+ }
+ return entries;
+ }
+
+ if (job.startsWith("-sce"))
+ {
+ job = job.substring(5, job.length()).trim();
+
+ File sceFile = new File(job);
+ if (sceFile.exists())
+ {
+ return getScenario(job, descPath, debug);
+ }
+ else
+ {
+ //look the scenario like this? :
+ // sw.SwXBodyText,sw.SwXTextCursor
+ ArrayList<String> subs = getSubObjects(job);
+ DescEntry[] entries = new DescEntry[subs.size()];
+
+ for (int i = 0; i < subs.size(); i++)
+ {
+ entries[i] = getDescriptionForSingleJob(
+ subs.get(i), descPath, debug);
+ }
+ return entries;
+ }
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ @Override
+ protected DescEntry getDescriptionForSingleJob(String job, String descPath,
+ boolean debug)
+ {
+ boolean isSingleInterface = job.indexOf("::") > 0;
+ fullJob = job;
+
+ if (isSingleInterface)
+ {
+ job = job.substring(0, job.indexOf("::"));
+ }
+
+ if (job.startsWith("bugs"))
+ {
+ DescEntry Entry = new DescEntry();
+ Entry.entryName = job;
+ Entry.longName = job;
+ Entry.EntryType = "bugdoc";
+ Entry.isOptional = false;
+ Entry.isToTest = true;
+ Entry.SubEntryCount = 0;
+ Entry.hasErrorMsg = false;
+ Entry.State = "non possible";
+
+ return Entry;
+ }
+
+ DescEntry entry = null;
+
+ if (descPath != null)
+ {
+ if (debug)
+ {
+ System.out.println("## reading from File " + descPath);
+ }
+
+ entry = getFromDirectory(descPath, job, debug);
+ }
+ else
+ {
+ if (debug)
+ {
+ System.out.println("## reading from jar");
+ }
+
+ entry = getFromClassPath(job);
+ }
+
+ boolean foundInterface = false;
+
+ if (isSingleInterface && (entry != null))
+ {
+ for (int i = 0; i < entry.SubEntryCount; i++)
+ {
+ if (!(entry.SubEntries[i].longName).equals(fullJob))
+ {
+ entry.SubEntries[i].isToTest = false;
+ }
+ else
+ {
+ foundInterface = true;
+ entry.SubEntries[i].isToTest = true;
+ }
+ }
+ }
+
+ if (isSingleInterface && !foundInterface || entry == null)
+ {
+ return setErrorDescription(entry,
+ "couldn't find a description for test '" + fullJob + "'");
+ }
+
+ return entry;
+ }
+
+ private static DescEntry[] getSubEntries(BufferedReader cvsFile,
+ DescEntry parent)
+ {
+ String line = "";
+ String old_ifc_name = "";
+ ArrayList<DescEntry> ifc_names = new ArrayList<DescEntry>();
+ ArrayList<DescEntry> meth_names = new ArrayList<DescEntry>();
+ DescEntry ifcDesc = null;
+
+ while (line != null)
+ {
+ try
+ {
+ line = cvsFile.readLine();
+ if (line == null)
+ {
+ continue;
+ }
+ if (line.startsWith("#"))
+ {
+ continue;
+ }
+ if (line.length() <= 0)
+ {
+ continue;
+ }
+// TODO Problem here
+
+ String ifc_name = ""; // = line.substring(line.indexOf(";") + 2, line.lastIndexOf(";") - 1);
+ String meth_name = ""; // = line.substring(line.lastIndexOf(";") + 2, line.length() - 1);
+ StringTokenizer aToken = new StringTokenizer(line, ";");
+ if (aToken.countTokens() < 3)
+ {
+ System.out.println("Wrong format: Line '" + line + "' is not supported.");
+ continue;
+ }
+ if (aToken.hasMoreTokens())
+ {
+ aToken.nextToken();
+ }
+ if (aToken.hasMoreTokens())
+ {
+ ifc_name = StringHelper.removeQuoteIfExists(aToken.nextToken());
+ }
+ if (aToken.hasMoreTokens())
+ {
+ meth_name = StringHelper.removeQuoteIfExists(aToken.nextToken());
+ }
+
+ DescEntry methDesc = createDescEntry(meth_name, ifc_name, parent);
+
+ if (!ifc_name.equals(old_ifc_name))
+ {
+ if (ifcDesc != null)
+ {
+ ifcDesc.SubEntries = getDescArray(meth_names.toArray());
+ ifcDesc.SubEntryCount = meth_names.size();
+
+ //mark service/interface as optional if all methods/properties are optional
+ boolean allOptional = true;
+
+ for (int k = 0; k < ifcDesc.SubEntryCount; k++)
+ {
+ if (!ifcDesc.SubEntries[k].isOptional)
+ {
+ allOptional = false;
+ }
+ }
+
+ if (!ifcDesc.isOptional && allOptional)
+ {
+ ifcDesc.isOptional = allOptional;
+ }
+
+ meth_names.clear();
+ ifc_names.add(ifcDesc);
+ }
+
+ ifcDesc = new DescEntry();
+ ifcDesc.isToTest = true;
+ old_ifc_name = ifc_name;
+
+ if (ifc_name.indexOf("#optional") > 0)
+ {
+ ifcDesc.isOptional = true;
+ ifc_name = ifc_name.substring(0, ifc_name.indexOf('#'));
+ }
+
+ String className = createClassName(ifc_name);
+
+ ifcDesc.EntryType = entryType;
+ ifcDesc.entryName = "ifc" + className;
+ ifcDesc.longName = parent.entryName + "::" + ifc_name;
+ }
+ meth_names.add(methDesc);
+
+ }
+ catch (java.io.IOException ioe)
+ {
+ parent.hasErrorMsg = true;
+ parent.ErrorMsg = "IOException while reading the description";
+ break;
+ }
+ }
+
+ if (ifcDesc == null) {
+ return null;
+ }
+
+ ifcDesc.SubEntries = getDescArray(meth_names.toArray());
+ ifcDesc.SubEntryCount = meth_names.size();
+
+ //mark service/interface as optional if all methods/properties are optional
+ boolean allOptional = true;
+
+ for (int k = 0; k < ifcDesc.SubEntryCount; k++)
+ {
+ if (!ifcDesc.SubEntries[k].isOptional)
+ {
+ allOptional = false;
+ }
+ }
+
+ if (!ifcDesc.isOptional && allOptional)
+ {
+ ifcDesc.isOptional = allOptional;
+ }
+
+ ifc_names.add(ifcDesc);
+
+ return getDescArray(makeArray(ifc_names));
+ }
+ private static String createClassName(String _ifc_name)
+ {
+ StringTokenizer st = new StringTokenizer(_ifc_name, ":");
+
+ int count = 3;
+
+ if (_ifc_name.startsWith("drafts"))
+ {
+ count = 4;
+ }
+
+ StringBuilder className = new StringBuilder();
+
+ for (int i = 0; st.hasMoreTokens(); i++)
+ {
+ String token = st.nextToken();
+
+ // skipping (drafts.)com.sun.star
+ if (i >= count)
+ {
+ if (!st.hasMoreTokens())
+ {
+ // inserting '_' before the last token
+ token = "_" + token;
+ }
+
+ className.append(".").append(token);
+ }
+ }
+ return className.toString();
+ }
+
+ private static String entryType;
+
+ private static DescEntry createDescEntry(String meth_name, String ifc_name, DescEntry parent)
+ {
+ entryType = "service";
+ DescEntry methDesc = new DescEntry();
+
+ if (meth_name.indexOf("#optional") > 0)
+ {
+ methDesc.isOptional = true;
+ meth_name = meth_name.substring(0, meth_name.indexOf('#'));
+ }
+
+ if (meth_name.endsWith("()"))
+ {
+ methDesc.EntryType = "method";
+ entryType = "interface";
+ }
+ else
+ {
+ methDesc.EntryType = "property";
+ entryType = "service";
+ }
+
+ methDesc.entryName = meth_name;
+ methDesc.isToTest = true;
+
+
+ String withoutHash = ifc_name;
+
+ if (ifc_name.indexOf("#optional") > 0)
+ {
+ withoutHash = ifc_name.substring(0, ifc_name.indexOf('#'));
+ }
+
+ methDesc.longName = parent.entryName + "::" + withoutHash + "::" + meth_name;
+
+ return methDesc;
+ }
+
+ /**
+ * This method ensures that XComponent will be the last in the list of interfaces
+ */
+ private static Object[] makeArray(ArrayList<DescEntry> entries)
+ {
+ Object[] entriesArray = entries.toArray();
+ ArrayList<Object> returnArray = new ArrayList<Object>();
+ Object addAtEnd = null;
+
+ for (int k = 0; k < entriesArray.length; k++)
+ {
+ DescEntry entry = (DescEntry) entriesArray[k];
+
+ if (entry.entryName.equals("ifc.lang._XComponent"))
+ {
+ addAtEnd = entry;
+ }
+ else
+ {
+ returnArray.add(entry);
+ }
+ }
+
+ if (addAtEnd != null)
+ {
+ returnArray.add(addAtEnd);
+ }
+
+ return returnArray.toArray();
+ }
+
+ private static DescEntry setErrorDescription(DescEntry entry,
+ String ErrorMsg)
+ {
+ if (entry == null)
+ {
+ entry = new DescEntry();
+ }
+ entry.hasErrorMsg = true;
+ entry.ErrorMsg = "Error while getting description for test '" +
+ fullJob + "' as an API test: " + ErrorMsg;
+
+ return entry;
+ }
+
+ private static DescEntry[] getDescArray(Object[] list)
+ {
+ DescEntry[] entries = new DescEntry[list.length];
+
+ for (int i = 0; i < list.length; i++)
+ {
+ entries[i] = (DescEntry) list[i];
+ }
+
+ return entries;
+ }
+
+ private DescEntry getFromClassPath(String aEntry)
+ {
+ int dotindex = aEntry.indexOf('.');
+
+ if (dotindex == -1)
+ {
+ return null;
+ }
+
+ String module = null;
+ String shortName = null;
+
+ if (aEntry.indexOf(".uno") == -1)
+ {
+ module = aEntry.substring(0, aEntry.indexOf('.'));
+ shortName = aEntry.substring(aEntry.indexOf('.') + 1);
+ }
+ else
+ {
+ module = aEntry.substring(0, aEntry.lastIndexOf('.'));
+ shortName = aEntry.substring(aEntry.lastIndexOf('.') + 1);
+ }
+
+ DescEntry theEntry = new DescEntry();
+ theEntry.entryName = aEntry;
+ theEntry.longName = aEntry;
+ theEntry.isOptional = false;
+ theEntry.EntryType = "component";
+ theEntry.isToTest = true;
+
+ BufferedReader csvFile = null;
+
+ java.net.URL url = this.getClass().getResource("/objdsc/" + module);
+
+ if (url == null)
+ {
+ return setErrorDescription(theEntry,
+ "couldn't find module '" + module + "'");
+ }
+
+ try
+ {
+ java.net.URLConnection con = url.openConnection();
+
+ String sEndsWithCSVName = "." + shortName.trim() + ".csv";
+ if (con instanceof java.net.JarURLConnection)
+ {
+ // get Jar file from connection
+ java.util.jar.JarFile f = ((java.net.JarURLConnection) con).getJarFile();
+
+ // Enumerate over all entries
+ java.util.Enumeration<JarEntry> e = f.entries();
+
+ String sStartModule = "/" + module + "/";
+ while (e.hasMoreElements())
+ {
+
+ String entry = e.nextElement().toString();
+
+ if ((entry.lastIndexOf(sStartModule) != -1) &&
+ entry.endsWith(sEndsWithCSVName))
+ {
+ InputStream input = this.getClass().getResourceAsStream("/" + entry);
+ csvFile = new BufferedReader(new InputStreamReader(input, "UTF-8"));
+ break;
+ }
+ }
+ }
+ else
+ {
+ InputStream in = con.getInputStream();
+ java.io.BufferedReader buf = new java.io.BufferedReader(new InputStreamReader(in, "UTF-8"));
+ while (true)
+ {
+ String entry = buf.readLine();
+ if (entry == null)
+ break;
+ if (entry.endsWith(sEndsWithCSVName))
+ {
+ System.out.println("FOUND ####");
+ InputStream input =
+ this.getClass().getResourceAsStream("/objdsc/" +
+ module +
+ "/" +
+ entry);
+ csvFile = new BufferedReader(new InputStreamReader(input, "UTF-8"));
+ break;
+ }
+ }
+
+ buf.close();
+ }
+ }
+ catch (java.io.IOException e)
+ {
+ e.printStackTrace();
+ }
+
+ if (csvFile == null)
+ {
+ return setErrorDescription(theEntry,
+ "couldn't find component '" +
+ theEntry.entryName + "'");
+ }
+
+ DescEntry[] subEntries = getSubEntries(csvFile, theEntry);
+
+ theEntry.SubEntryCount = subEntries != null ? subEntries.length : 0;
+ theEntry.SubEntries = subEntries;
+
+ try
+ {
+ csvFile.close();
+ }
+ catch (java.io.IOException ioe)
+ {
+ System.out.println("Exception while closing csvFile");
+ }
+
+ return theEntry;
+ }
+
+ private static DescEntry getFromDirectory(String descPath, String entry,
+ boolean debug)
+ {
+ int dotindex = entry.indexOf('.');
+
+ if (dotindex == -1)
+ {
+ return null;
+ }
+
+ String fs = System.getProperty("file.separator");
+ String module = null;
+ String shortName = null;
+
+ if (entry.indexOf(".uno") == -1)
+ {
+ module = entry.substring(0, entry.indexOf('.'));
+ shortName = entry.substring(entry.indexOf('.') + 1);
+ }
+ else
+ {
+ module = entry.substring(0, entry.lastIndexOf('.'));
+ shortName = entry.substring(entry.lastIndexOf('.') + 1);
+ }
+
+ DescEntry aEntry = new DescEntry();
+ aEntry.entryName = entry;
+ aEntry.longName = entry;
+ aEntry.isOptional = false;
+ aEntry.EntryType = "component";
+ aEntry.isToTest = true;
+
+ if (debug)
+ {
+ System.out.println("Parsing Description Path: " + descPath);
+ System.out.println("Searching module: " + module);
+ System.out.println("For the Component " + shortName);
+ }
+
+ File modPath = new File(descPath + fs + module);
+
+ if (!modPath.exists())
+ {
+ return setErrorDescription(aEntry,
+ "couldn't find module '" + module + "'");
+ }
+
+ String[] files = modPath.list();
+ String found = "none";
+
+ for (int i = 0; i < files.length; i++)
+ {
+ if (files[i].endsWith("." + shortName + ".csv"))
+ {
+ found = files[i];
+ System.out.println("found " + found);
+ break;
+ }
+ }
+
+ if (found.equals("none"))
+ {
+ return setErrorDescription(aEntry,
+ "couldn't find component '" + entry + "'");
+ }
+
+ String aUrl = descPath + fs + module + fs + found;
+
+ BufferedReader csvFile = null;
+
+ try
+ {
+ csvFile = new BufferedReader(new FileReader(aUrl));
+ }
+ catch (java.io.FileNotFoundException fnfe)
+ {
+ return setErrorDescription(aEntry, "couldn't find file '" + aUrl + "'");
+ }
+
+ DescEntry[] subEntries = getSubEntries(csvFile, aEntry);
+
+ try
+ {
+ csvFile.close();
+ }
+ catch (java.io.IOException ioe)
+ {
+ System.out.println("Exception while closing csvFile");
+ }
+
+ aEntry.SubEntryCount = subEntries != null ? subEntries.length : 0;
+ aEntry.SubEntries = subEntries;
+
+ return aEntry;
+ }
+
+ @Override
+ protected ArrayList<String> getSubInterfaces(String job)
+ {
+ ArrayList<String> namesList = new ArrayList<String>();
+ StringTokenizer st = new StringTokenizer(job, ",");
+
+ while (st.hasMoreTokens())
+ {
+ String token = st.nextToken();
+
+ if (token.indexOf('.') < 0)
+ {
+ namesList.add(token);
+ }
+ }
+
+ return namesList;
+ }
+
+ private ArrayList<String> getSubObjects(String job)
+ {
+ ArrayList<String> namesList = new ArrayList<String>();
+ StringTokenizer st = new StringTokenizer(job, ",");
+
+ while (st.hasMoreTokens())
+ {
+ namesList.add(st.nextToken());
+ }
+
+ return namesList;
+ }
+
+ @Override
+ protected String[] createScenario(String descPath, String job,
+ boolean debug)
+ {
+ String[] scenario = null;
+
+ if (descPath != null)
+ {
+ if (debug)
+ {
+ System.out.println("## reading from File " + descPath);
+ }
+
+ scenario = getScenarioFromDirectory(descPath, job);
+ }
+ else
+ {
+ if (debug)
+ {
+ System.out.println("## reading from jar");
+ }
+
+ scenario = getScenarioFromClassPath(job);
+ }
+
+ return scenario;
+ }
+
+ private String[] getScenarioFromDirectory(String descPath, String job)
+ {
+ String[] modules = null;
+ ArrayList<String> componentList = new ArrayList<String>();
+
+ if (!job.equals("unknown") && !job.equals("listall"))
+ {
+ modules = new String[]
+ {
+ job
+ };
+ }
+ else
+ {
+ File dirs = new File(descPath);
+
+ if (dirs.exists()) {
+ modules = dirs.list();
+ }
+ }
+
+ int moduleLength = modules != null ? modules.length : 0;
+
+ for (int i = 0; i < moduleLength; ++i)
+ {
+ if (!isUnusedModule(modules[i]))
+ {
+ File moduleDir = new File(descPath + System.getProperty("file.separator") + modules[i]);
+ if (moduleDir.exists())
+ {
+ String[] components = moduleDir.list();
+ for (int j = 0; j < components.length; j++)
+ {
+ if (components[j].endsWith(".csv"))
+ {
+ String toAdd = getComponentForString(components[j], modules[i]);
+ toAdd = "-o " + modules[i] + "." + toAdd;
+ componentList.add(toAdd);
+ }
+ }
+ }
+ }
+ }
+
+ Collections.sort(componentList);
+ String[] scenario = componentList.toArray(new String[componentList.size()]);
+ return scenario;
+ }
+
+ private String[] getScenarioFromClassPath(String job)
+ {
+ String subdir = "/";
+
+ if (!job.equals("unknown") && !job.equals("listall"))
+ {
+ subdir += job;
+ }
+
+ java.net.URL url = this.getClass().getResource("/objdsc" + subdir);
+
+ if (url == null)
+ {
+ return null;
+ }
+
+ ArrayList<String> scenarioList = new ArrayList<String>();
+
+ try
+ {
+ java.net.URLConnection con = url.openConnection();
+
+ if (con instanceof java.net.JarURLConnection)
+ {
+ // get Jar file from connection
+ java.util.jar.JarFile f = ((java.net.JarURLConnection) con).getJarFile();
+
+ // Enumerate over all entries
+ java.util.Enumeration<JarEntry> e = f.entries();
+
+ while (e.hasMoreElements())
+ {
+ String entry = e.nextElement().toString();
+
+ if (entry.startsWith("objdsc" + subdir) &&
+ (entry.indexOf("CVS") < 0) &&
+ !entry.endsWith("/"))
+ {
+ int startMod = entry.indexOf('/');
+ int endMod = entry.lastIndexOf('/');
+ String module = entry.substring(startMod + 1, endMod);
+ String component = getComponentForString(
+ entry.substring(endMod + 1,
+ entry.length()),
+ module);
+
+ if (!isUnusedModule(module))
+ {
+ scenarioList.add("-o " + module + "." +
+ component);
+ }
+ }
+ }
+ }
+ }
+ catch (java.io.IOException e)
+ {
+ e.printStackTrace();
+ }
+
+ Collections.sort(scenarioList);
+ String[] scenario = scenarioList.toArray(new String[scenarioList.size()]);
+ return scenario;
+ }
+
+ private String getComponentForString(String full, String module)
+ {
+ String component = "";
+
+
+ //cutting .csv
+ full = full.substring(0, full.length() - 4);
+
+ //cutting component
+ int lastdot = full.lastIndexOf('.');
+ component = full.substring(lastdot + 1, full.length());
+
+ if (module.equals("file") || module.equals("xmloff"))
+ {
+ String withoutComponent = full.substring(0, lastdot);
+ int preLastDot = withoutComponent.lastIndexOf('.');
+ component = withoutComponent.substring(preLastDot + 1,
+ withoutComponent.length()) +
+ "." + component;
+ }
+
+ return component;
+ }
+
+ private boolean isUnusedModule(String moduleName)
+ {
+ ArrayList<String> removed = new ArrayList<String>();
+ removed.add("acceptor");
+ removed.add("brdgfctr");
+ removed.add("connector");
+ removed.add("corefl");
+ removed.add("cpld");
+ removed.add("defreg");
+ removed.add("dynamicloader");
+ removed.add("impreg");
+ removed.add("insp");
+ removed.add("inv");
+ removed.add("invadp");
+ removed.add("javaloader");
+ removed.add("jen");
+ removed.add("namingservice");
+ removed.add("proxyfac");
+ removed.add("rdbtdp");
+ removed.add("remotebridge");
+ removed.add("simreg");
+ removed.add("smgr");
+ removed.add("stm");
+ removed.add("tcv");
+ removed.add("tdmgr");
+ removed.add("ucprmt");
+ removed.add("uuresolver");
+
+ return removed.contains(moduleName);
+ }
+}
diff --git a/qadevOOo/runner/helper/AppProvider.java b/qadevOOo/runner/helper/AppProvider.java
new file mode 100644
index 000000000..a42411ac6
--- /dev/null
+++ b/qadevOOo/runner/helper/AppProvider.java
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package helper;
+
+import java.io.UnsupportedEncodingException;
+
+/**
+ *
+ * Interface to get a Manager to access the application to check
+ */
+public interface AppProvider {
+
+ /**
+ * Method to get the desired Manager
+ */
+ Object getManager(lib.TestParameters param) throws UnsupportedEncodingException;
+
+ /**
+ * Method to dispose the desired Manager
+ */
+ boolean disposeManager(lib.TestParameters param);
+
+ /**
+ * Close an office.
+ * @param param The test parameters.
+ * @param closeIfPossible If true, close even if
+ * it was running before the test
+ * @return True, if close worked.
+ */
+ boolean closeExistingOffice(lib.TestParameters param,
+ boolean closeIfPossible);
+}
diff --git a/qadevOOo/runner/helper/CfgParser.java b/qadevOOo/runner/helper/CfgParser.java
new file mode 100644
index 000000000..ea9e7b5c0
--- /dev/null
+++ b/qadevOOo/runner/helper/CfgParser.java
@@ -0,0 +1,124 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package helper;
+
+import java.io.FileInputStream;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+
+import lib.TestParameters;
+import util.PropertyName;
+
+/**
+ * This class parses the ini files and stores the data
+ * <br>
+ * inside TestParameters
+ */
+public class CfgParser
+{
+
+ private boolean debug = false;
+ private String iniFile = "";
+
+ public CfgParser(String ini)
+ {
+ this.iniFile = ini;
+ }
+
+ public void getIniParameters(TestParameters param)
+ {
+ debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
+ Properties cfg = getProperties(iniFile);
+
+ if (cfg != null)
+ {
+ Enumeration<Object> cfgEnum = cfg.keys();
+ while (cfgEnum.hasMoreElements())
+ {
+ String pName = (String) cfgEnum.nextElement();
+ String pValue = cfg.getProperty(pName);
+
+ if (pValue != null)
+ {
+ pValue = pValue.trim();
+ }
+
+ param.put(pName.trim(), pValue);
+
+ if (pName.equals(PropertyName.TEST_DOCUMENT_PATH))
+ {
+
+ param.put("DOCPTH", pValue);
+ System.setProperty("DOCPTH", (String) pValue);
+
+ }
+ else if (pName.equals(PropertyName.SRC_ROOT))
+ {
+
+ System.setProperty(pName, (String) pValue);
+
+ }
+ }
+ }
+
+ debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
+ }
+
+ private Properties getProperties(String name)
+ {
+ // get the resource file
+ Properties prop = new Properties();
+ if (debug)
+ {
+ System.out.println("Looking for " + name);
+ }
+ try
+ {
+ FileInputStream propFile = new FileInputStream(name);
+ prop.load(propFile);
+ System.out.println("Parsing properties from " + name);
+ propFile.close();
+ }
+ catch (Exception e)
+ {
+ try
+ {
+ java.net.URL url = this.getClass().getResource("/" + name);
+ if (url != null)
+ {
+ System.out.println("Parsing properties from " + name);
+ java.net.URLConnection connection = url.openConnection();
+ java.io.InputStream in = connection.getInputStream();
+ prop.load(in);
+ }
+ }
+ catch (Exception ex)
+ {
+ //Exception while reading prop-file, returning null
+ return null;
+ }
+ }
+
+ return prop;
+ }
+
+}
diff --git a/qadevOOo/runner/helper/ClParser.java b/qadevOOo/runner/helper/ClParser.java
new file mode 100644
index 000000000..1dd70dbb9
--- /dev/null
+++ b/qadevOOo/runner/helper/ClParser.java
@@ -0,0 +1,137 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package helper;
+
+import java.io.File;
+import java.util.HashMap;
+
+import lib.TestParameters;
+import util.PropertyName;
+
+/**
+ * This class parses commandline Argument and stores <br>
+ * them into TestParameter
+ */
+public class ClParser
+{
+ /*
+ * Parses the commandline argument and puts them<br>
+ * into the TestParameters
+ */
+
+ public void getCommandLineParameter(TestParameters param, String[] args)
+ {
+ for (int i = 0; i < args.length;)
+ {
+ String pName = getParameterFor(args[i]).trim();
+ String pValue = "";
+ if (pName.equals("TestJob"))
+ {
+ if (args.length > (i + 1))
+ {
+ pValue = args[i].trim() + " " + args[i + 1].trim();
+ i += 2;
+ }
+ else
+ {
+ pValue = args[i].trim() + " unknown";
+ i += 2;
+ }
+ }
+ else
+ {
+ if ((i + 1) < args.length)
+ {
+ pValue = args[i + 1].trim();
+
+ if (pValue.startsWith("-"))
+ {
+ i++;
+ pValue = "yes";
+ }
+ else if (pValue.startsWith("'"))
+ {
+ i++;
+ while (!pValue.endsWith("'"))
+ {
+ i++;
+ pValue = pValue + " " + args[i].trim();
+
+ }
+ pValue = pValue.replace("'", "");
+ i++;
+ }
+ else
+ {
+ i += 2;
+ }
+
+ if (pName.equals("TestDocumentPath"))
+ {
+ System.setProperty(
+ "DOCPTH", new File(pValue).getAbsolutePath());
+ }
+ else if (pName.equals(PropertyName.SRC_ROOT))
+ {
+ System.setProperty(pName, pValue);
+
+ }
+ }
+ else
+ {
+ pValue = "yes";
+ i++;
+ }
+ }
+
+ param.put(pName, pValue);
+ }
+ }
+
+ /**
+ * Map command-line Parameters to TestParameters
+ */
+ private static final java.util.Map<String,String> COMMAND_LINE_OPTION_TO_TEST_PARAMETER = new HashMap<String,String>();
+ static {
+ COMMAND_LINE_OPTION_TO_TEST_PARAMETER.put("-cs", "ConnectionString");
+ COMMAND_LINE_OPTION_TO_TEST_PARAMETER.put("-tb", "TestBase");
+ COMMAND_LINE_OPTION_TO_TEST_PARAMETER.put("-tdoc", "TestDocumentPath");
+ COMMAND_LINE_OPTION_TO_TEST_PARAMETER.put("-objdsc", "DescriptionPath");
+ COMMAND_LINE_OPTION_TO_TEST_PARAMETER.put("-cmd", "AppExecutionCommand");
+ COMMAND_LINE_OPTION_TO_TEST_PARAMETER.put("-o", "TestJob");
+ COMMAND_LINE_OPTION_TO_TEST_PARAMETER.put("-sce", "TestJob");
+ COMMAND_LINE_OPTION_TO_TEST_PARAMETER.put("-p", "TestJob");
+ COMMAND_LINE_OPTION_TO_TEST_PARAMETER.put("-aca", "AdditionalConnectionArguments");
+ COMMAND_LINE_OPTION_TO_TEST_PARAMETER.put("-xcl", "ExclusionList");
+ COMMAND_LINE_OPTION_TO_TEST_PARAMETER.put("-debug", "DebugIsActive");
+ COMMAND_LINE_OPTION_TO_TEST_PARAMETER.put("-log", "LoggingIsActive");
+ COMMAND_LINE_OPTION_TO_TEST_PARAMETER.put("-dbout", "DataBaseOut");
+ }
+
+ private String getParameterFor(String name)
+ {
+ String ret = COMMAND_LINE_OPTION_TO_TEST_PARAMETER.get(name);
+
+ if (ret == null)
+ {
+ ret = name.substring(1);
+ }
+
+ return ret;
+ }
+} \ No newline at end of file
diff --git a/qadevOOo/runner/helper/ComplexDescGetter.java b/qadevOOo/runner/helper/ComplexDescGetter.java
new file mode 100644
index 000000000..444ff181b
--- /dev/null
+++ b/qadevOOo/runner/helper/ComplexDescGetter.java
@@ -0,0 +1,183 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package helper;
+
+import java.util.ArrayList;
+
+import share.ComplexTest;
+import share.DescEntry;
+import share.DescGetter;
+import share.LogWriter;
+import util.DynamicClassLoader;
+
+import complexlib.ComplexTestCase;
+
+/**
+ *
+ */
+public class ComplexDescGetter extends DescGetter
+{
+
+ private ComplexTest testClass;
+
+ /** Creates new ComplexDescGetter */
+ public ComplexDescGetter()
+ {
+ testClass = null;
+ }
+
+ @Override
+ public DescEntry[] getDescriptionFor(String entry, String DescPath,
+ boolean debug)
+ {
+ // read scenario file
+ if (entry.startsWith("-sce"))
+ {
+ DescEntry[] entries = getScenario(entry.substring(5), null, debug);
+ return entries;
+ }
+ // one single job
+ else if (entry.startsWith("-o"))
+ {
+ DescEntry dEntry = getDescriptionForSingleJob(entry.substring(3), null, debug);
+ if (dEntry != null)
+ {
+ return new DescEntry[]
+ {
+ dEntry
+ };
+ }
+ }
+ System.out.println("Could not get a testjob with parameter '" + entry + "'");
+ // no job available
+ return null;
+ }
+
+ @Override
+ protected DescEntry getDescriptionForSingleJob(String className, String descPath, boolean debug)
+ {
+ DynamicClassLoader dcl = new DynamicClassLoader();
+ String methodNames[] = null;
+
+ if (debug)
+ {
+ System.out.println("Searching Class: " + className);
+ }
+
+ int index = className.indexOf("::");
+ if (index != -1)
+ {
+ // case1: method()
+ // case2: method(param1,param2)
+ // case3: method1(param1,param2),method2(param1,param2)
+ String method = className.substring(index + 2);
+ className = className.substring(0, index);
+ ArrayList<String> methods = new ArrayList<String>();
+
+ String[] split = method.split("(?<=\\)),(?=\\w+)");
+
+ for (int i = 0; i < split.length; i++)
+ {
+ String meth = split[i];
+
+ if (meth.endsWith("()"))
+ {
+ meth = meth.substring(0, meth.length() - 2);
+ }
+
+ methods.add(meth);
+ }
+
+ methodNames = methods.toArray(new String[methods.size()]);
+ }
+
+ // create an instance
+ try
+ {
+ testClass = (ComplexTestCase) dcl.getInstance(className);
+ }
+ catch (java.lang.IllegalArgumentException e)
+ {
+ System.out.println("Error while getting description for test '" + className + "' as a Complex test.");
+ return null;
+ }
+ catch (java.lang.ClassCastException e)
+ {
+ System.out.println("The given class '" + className + "' is not a Complex test.");
+ return null;
+ }
+
+
+ if (debug)
+ {
+ System.out.println("Got test: " + ((Object) testClass).toString());
+ }
+
+ String testObjectName = className;
+ String[] testMethodNames = testClass.getTestMethodNames();
+ if (methodNames != null)
+ {
+ testMethodNames = methodNames;
+ }
+
+ DescEntry dEntry = createTestDesc(testObjectName, className, testMethodNames, null);
+
+ return dEntry;
+ }
+
+ /**
+ * Creates a description entry for the given parameter
+ * @param testObjectName the name of the object
+ * @param className the class name of the class to load
+ * @param testMethodNames list of all methods to test
+ * @return filled description entry
+ */
+ private DescEntry createTestDesc(String testObjectName, String className, String[] testMethodNames, LogWriter log)
+ {
+
+ DescEntry dEntry = new DescEntry();
+
+ dEntry.entryName = testObjectName;
+ dEntry.longName = className;
+ dEntry.isOptional = false;
+ dEntry.EntryType = "unit";
+ dEntry.isToTest = true;
+ dEntry.Logger = log;
+ dEntry.SubEntryCount = testMethodNames.length;
+ dEntry.SubEntries = new DescEntry[dEntry.SubEntryCount];
+ for (int i = 0; i < dEntry.SubEntryCount; i++)
+ {
+ DescEntry aEntry = new DescEntry();
+ aEntry.entryName = testMethodNames[i];
+ aEntry.longName = testObjectName + "::" + aEntry.entryName;
+ aEntry.isOptional = false;
+ aEntry.EntryType = "method";
+ aEntry.isToTest = true;
+ dEntry.SubEntries[i] = aEntry;
+ dEntry.Logger = log;
+ }
+
+ return dEntry;
+ }
+
+ @Override
+ protected String[] createScenario(String descPath, String job, boolean debug)
+ {
+ return new String[] {};
+ }
+}
diff --git a/qadevOOo/runner/helper/ConfigHelper.java b/qadevOOo/runner/helper/ConfigHelper.java
new file mode 100644
index 000000000..73953c1c7
--- /dev/null
+++ b/qadevOOo/runner/helper/ConfigHelper.java
@@ -0,0 +1,303 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package helper;
+
+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.*;
+
+/**
+ * This <CODE>ConfigHelper</CODE> makes it possible to access the
+ * configuration and change their content.<P>
+ * <P>
+ * Example: <P>
+ * Listing of the <CODE>Configuration</CODE> Views.xcu:<P>
+ * &lt;oor:component-data xmlns:oor=&quot;http://openoffice.org/2001/registry&quot; xmlns:xs=&quot;http://www.w3.org/2001/XMLSchema&quot; oor:name=&quot;Views&quot; oor:package=&quot;org.openoffice.Office&quot;&gt;<p>
+ * &lt;node oor:name=&quot;Windows&quot;&gt;<P>
+ * <&lt;node oor:name=&quot;SplitWindow0&quot; oor:op=&quot;replace&quot;&gt;<P>
+ * &lt;prop oor:name=&quot;Visible&quot; oor:type=&quot;xs:boolean&quot;&gt;<P>
+ * &lt;value&gt;false&lt;/value&gt;<P>
+ * &lt;/prop&gt;<P>
+ * &lt;prop oor:name=&quot;WindowState&quot; oor:type=&quot;xs:string&quot;&gt;<P>
+ * &lt;value/&gt;<P>
+ * &lt;/prop&gt;<P>
+ * &lt;node oor:name=&quot;UserData&quot;&gt;<P>
+ * &lt;prop oor:name=&quot;UserItem&quot; oor:op=&quot;replace&quot;
+ * oor:type=&quot;xs:string&quot;&gt;<P>
+ * &lt;value&gt;V1,2,0&lt;/value&gt;<P>
+ * &lt;/prop&gt;<P>
+ * &lt;/node&gt;<P>
+ * &lt;/node&gt;<P>
+ * &lt;/node&gt;<P>
+ * <P>
+ * <CODE>Definition</CODE><P>
+ * <ul>
+ * <li><CODE>&lt;node oor:name=&quot;Windows&quot;&gt;</CODE>
+ * represents a <CODE>Set</CODE> and is a <CODE>XNameContainer</CODE></LI>
+ * <li><CODE>&lt;node oor:name=&quot;SplitWindow0&quot;&gt;</CODE>
+ * represents a <CODE>Group</CODE> and is a <CODE>XNameReplace</CODE></LI>
+ * <li><CODE>&lt;prop oor:name=&quot;Visible&quot;&gt;</CODE>
+ * represents a pr<CODE></CODE>operty of the group</li>
+ * <li><CODE>&lt;node oor:name=&quot;UserData&quot;&gt;</CODE>
+ * represents a <CODE>extensible group</CODE> and is a <CODE>XNameContainer</CODE></LI>
+ * <li><CODE>&lt;prop oor:name=&quot;UserItem&quot;&gt;</CODE>
+ * represents a <CODE>property</CODE> of the extensible group</LI>
+ * </UL>
+ * We assume in the following examples the existence of:<P>
+ * <CODE>ConfigHelper aConfig = new ConfigHelper(xMSF, "org.openoffice.Office.Views", false);</CODE>
+ * <ul>
+ * <li>If you like to insert a new <CODE>Group</CODE> into the <CODE>Set</CODE> "Windows":<p>
+ * <CODE>XNameReplace xMyGroup = aConfig.getOrInsertGroup("Windows", "myGroup");</CODE><P>
+ * The method <CODE>getOrInsertGroup()</CODE> uses the
+ * <CODE>XSingleServiceFactory</CODE> to create the skeleton of a new group.
+ *
+ * </li>
+ * <li>If you like to change the property "WindowState" of "myGroup"
+ * of the Set "Windows"<p>
+ * <CODE>aConfig.updateGroupProperty(
+ * "Windows","myGroup", "WindowState", "952,180,244,349;1;0,0,0,0;");</CODE>
+ * </li>
+ * <li>If you like to change the property "myProp" of the extensible group
+ * "myExtGroup" which is an extensible group of "my2ndGroup" of the
+ * Set "Windows":<p>
+ * <CODE>aConfig.insertOrUpdateExtensibleGroupProperty(
+ * "Windows", "my2ndGroup", "myExtGroup", "myProp","TheValue");</CODE>
+ * </li>
+ * </ul>
+ */
+public class ConfigHelper
+{
+ private final XHierarchicalNameAccess m_xConfig;
+
+
+ public ConfigHelper(XMultiServiceFactory xSMGR ,
+ String sConfigPath ,
+ boolean bReadOnly )
+ throws com.sun.star.uno.Exception
+ {
+ XMultiServiceFactory xConfigRoot = UnoRuntime.queryInterface(
+ XMultiServiceFactory.class,
+ 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 = UnoRuntime.queryInterface(
+ XHierarchicalNameAccess.class,
+ aConfig);
+
+ if (m_xConfig == null)
+ throw new com.sun.star.uno.Exception("Could not open configuration \""+sConfigPath+"\"");
+ }
+
+
+ /**
+ * Updates the configuration.<p>
+ * This must be called after you have changed the configuration
+ * else you changes will be lost.
+ */
+ public void flush()
+ {
+ try
+ {
+ XChangesBatch xBatch = UnoRuntime.queryInterface(
+ XChangesBatch.class,
+ m_xConfig);
+ xBatch.commitChanges();
+ }
+ catch(com.sun.star.uno.Exception ex)
+ {}
+ }
+
+
+
+
+
+
+
+
+ /**
+ * Insert a structured node (group) in a name container (set)
+ * or else update it and return the <CODE>XNameReplace</CODE> of it.<P>
+ * The <CODE>XSingleServiceFacttory</CODE> of the <CODE>set</CODE> will be used
+ * to create a new group. This group is specific to its set and
+ * creates defined entries.
+ * @return The [inserted] group of the set
+ * @param groupName The name of the goup which should be returned
+ * @param setName The name of the set
+ * @throws com.sun.star.uno.Exception throws
+ * <CODE>com.sun.star.uno.Exception</CODE> on any error.
+ */
+ public XNameReplace getOrInsertGroup(String setName, String groupName)
+ throws com.sun.star.uno.Exception
+
+ {
+ XNameContainer xSetCont = this.getSet(setName);
+
+ XNameReplace xChildAccess = null;
+
+ try {
+ xSetCont.getByName(groupName);
+ xChildAccess = UnoRuntime.queryInterface(
+ XNameReplace.class,xSetCont);
+ } catch(com.sun.star.container.NoSuchElementException e) {
+ // proceed with inserting
+ }
+
+ if (xChildAccess == null) {
+ XSingleServiceFactory xChildfactory = UnoRuntime.queryInterface(XSingleServiceFactory.class,xSetCont);
+
+ Object xNewChild = xChildfactory.createInstance();
+
+ xSetCont.insertByName(groupName, xNewChild);
+
+ xChildAccess = UnoRuntime.queryInterface(XNameContainer.class,xNewChild);
+ }
+
+ return xChildAccess;
+ }
+
+ /**
+ * Update a property of a group container of a set container
+ * @param setName the name of the <CODE>set</CODE> which contains the <CODE>group</CODE>
+ * @param groupName the name of the <CODE>group</CODE> which property should be changed
+ * @param propName the name of the property which should be changed
+ * @param propValue the value the property should get
+ * @throws com.sun.star.uno.Exception throws <CODE>com.sun.star.uno.Exception</CODE> on any error.
+ */
+ public void updateGroupProperty(String setName,
+ String groupName,
+ String propName,
+ Object propValue)
+ throws com.sun.star.uno.Exception
+ {
+ XNameContainer xSetCont = this.getSet(setName);
+
+ XPropertySet xProp = null;
+ try {
+ xProp = UnoRuntime.queryInterface(
+ XPropertySet.class,
+ xSetCont.getByName(groupName));
+ } catch (com.sun.star.container.NoSuchElementException ex){
+ throw new com.sun.star.uno.Exception(ex,
+ "could not get group '" + groupName +
+ "' from set '"+ setName +"'");
+ }
+ try{
+ xProp.setPropertyValue(propName, propValue);
+ } catch (com.sun.star.uno.Exception ex) {
+ throw new com.sun.star.uno.Exception(ex,
+ "could not set property '" + propName +
+ "' from group '"+ groupName +
+ "' from set '"+ setName +"'");
+ }
+ }
+
+
+ /**
+ * Insert a property in an extensible group container or else update it
+ * @param setName the name of the <CODE>set</CODE> which contains the <CODE>group</CODE>
+ * @param group The name of the <CODE>group</CODE> which contains the <CODE>extensible group</CODE>.
+ * @param extGroup The name of the <CODE>extensible group</CODE> which
+ * [should] contain the property
+ * @param propName The name of the property.
+ * @param propValue The value of the property.
+ * @throws com.sun.star.uno.Exception throws <CODE>com.sun.star.uno.Exception</CODE> on any error.
+ */
+ public void insertOrUpdateExtensibleGroupProperty(
+ String setName,
+ String group,
+ String extGroup,
+ String propName,
+ Object propValue)
+ throws com.sun.star.uno.Exception
+ {
+ XNameContainer xSetCont = this.getSet(setName);
+
+ XNameReplace xGroupAccess = null;
+ XNameContainer xExtGroupCont = null;
+
+ try {
+ Object xGroup=xSetCont.getByName(group);
+ xGroupAccess = UnoRuntime.queryInterface(
+ XNameReplace.class,xGroup);
+ } catch(com.sun.star.container.NoSuchElementException ex) {
+ throw new com.sun.star.uno.Exception(ex,
+ "could not get group '" + group +
+ "' from set '"+ setName +"'");
+ }
+
+ try {
+ Object xGroup=xGroupAccess.getByName(extGroup);
+ xExtGroupCont = UnoRuntime.queryInterface(
+ XNameContainer.class,xGroup);
+ } catch(com.sun.star.container.NoSuchElementException ex) {
+ throw new com.sun.star.uno.Exception(ex,
+ "could not get extensible group '"+extGroup+
+ "' from group '"+ group +
+ "' from set '"+ setName +"'");
+ }
+
+ try {
+ xExtGroupCont.insertByName(propName, propValue);
+ }
+ catch(com.sun.star.container.ElementExistException e) {
+ xExtGroupCont.replaceByName(propName, propValue);
+ }
+
+ }
+
+
+ /**
+ * Returns a <CODE>XNameContainer</CODE> of the <CODE>Set</CODE>
+ * of the <CODE>Configuration</CODE>
+ * @param setName the name of the Set which should be returned
+ * @throws com.sun.star.uno.Exception on any error
+ * @return A XNameContainer of the Set
+ */
+ private XNameContainer getSet(String setName)
+ throws com.sun.star.uno.Exception
+ {
+ XNameReplace xCont = UnoRuntime.queryInterface(XNameReplace.class, m_xConfig);
+
+ Object oSet = xCont.getByName(setName);
+
+ if (oSet == null)
+ throw new com.sun.star.uno.Exception(
+ "could not get set '" + setName + ": null");
+
+ return UnoRuntime.queryInterface(
+ XNameContainer.class, oSet);
+
+ }
+}
diff --git a/qadevOOo/runner/helper/ConfigurationRead.java b/qadevOOo/runner/helper/ConfigurationRead.java
new file mode 100644
index 000000000..72346a2e7
--- /dev/null
+++ b/qadevOOo/runner/helper/ConfigurationRead.java
@@ -0,0 +1,82 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package helper;
+
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.container.XHierarchicalNameAccess;
+import com.sun.star.container.NoSuchElementException;
+import com.sun.star.beans.PropertyValue;
+import com.sun.star.beans.PropertyState;
+import com.sun.star.uno.UnoRuntime;
+
+/**
+ * Read configuration settings.
+ */
+public class ConfigurationRead {
+
+ private XHierarchicalNameAccess root = null;
+
+ /**
+ * Creates new ConfigurationRead
+ * @param xMSF An instance of service
+ * "com.sun.star.configuration.ConfigurationProvider"
+ * @param rootnode The root of the configuration nodes.
+ */
+ private ConfigurationRead(XMultiServiceFactory xMSF, String rootnode) {
+
+ PropertyValue [] nodeArgs = new PropertyValue [1];
+ PropertyValue nodepath = new PropertyValue();
+ nodepath.Name = "nodepath";
+ nodepath.Value = rootnode;
+ nodepath.Handle = -1;
+ nodepath.State = PropertyState.DEFAULT_VALUE;
+ nodeArgs[0]=nodepath;
+
+ try {
+ Object rootObject = xMSF.createInstanceWithArguments(
+ "com.sun.star.configuration.ConfigurationAccess",
+ nodeArgs);
+
+ root = UnoRuntime.queryInterface(
+ XHierarchicalNameAccess.class, rootObject);
+ }
+ catch(com.sun.star.uno.Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Creates new ConfigurationRead. This uses "org.openoffice.Setup"
+ * as default root name.
+ * @param xMSF An instance of service
+ * "com.sun.star.configuration.ConfigurationProvider"
+ */
+ public ConfigurationRead(XMultiServiceFactory xMSF) {
+ this(xMSF, "org.openoffice.Setup");
+ }
+
+ /**
+ * Get contents of a node by its hierarchical name.
+ * @param name The hierarchical name of the node.
+ * @return The contents as an object
+ */
+ public Object getByHierarchicalName(String name) throws NoSuchElementException {
+ return root.getByHierarchicalName(name);
+ }
+
+}
diff --git a/qadevOOo/runner/helper/ContextMenuInterceptor.java b/qadevOOo/runner/helper/ContextMenuInterceptor.java
new file mode 100644
index 000000000..c0961e66c
--- /dev/null
+++ b/qadevOOo/runner/helper/ContextMenuInterceptor.java
@@ -0,0 +1,131 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+package helper;
+
+import com.sun.star.beans.UnknownPropertyException;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.container.XIndexContainer;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.ui.ActionTriggerSeparatorType;
+import com.sun.star.ui.ContextMenuInterceptorAction;
+import com.sun.star.ui.XContextMenuInterceptor;
+import com.sun.star.uno.UnoRuntime;
+
+public class ContextMenuInterceptor implements XContextMenuInterceptor {
+
+ public ContextMenuInterceptorAction notifyContextMenuExecute(
+ com.sun.star.ui.ContextMenuExecuteEvent aEvent ) throws RuntimeException {
+ try {
+ // Retrieve context menu container and query for service factory to
+ // create sub menus, menu entries and separators
+ XIndexContainer xContextMenu = aEvent.ActionTriggerContainer;
+ XMultiServiceFactory xMenuElementFactory =
+ UnoRuntime.queryInterface(
+ XMultiServiceFactory.class, xContextMenu );
+
+ if ( xMenuElementFactory != null ) {
+
+ // create root menu entry for sub menu and sub menu
+ XPropertySet xRootMenuEntry =
+ UnoRuntime.queryInterface(
+ XPropertySet.class,
+ xMenuElementFactory.createInstance("com.sun.star.ui.ActionTrigger" ));
+
+ // create a line separator for our new help sub menu
+ XPropertySet xSeparator =
+ UnoRuntime.queryInterface(
+ XPropertySet.class,
+ xMenuElementFactory.createInstance("com.sun.star.ui.ActionTriggerSeparator" ) );
+ Short aSeparatorType = Short.valueOf( ActionTriggerSeparatorType.LINE );
+ xSeparator.setPropertyValue( "SeparatorType", aSeparatorType );
+
+ // query sub menu for index container to get access
+ XIndexContainer xSubMenuContainer =
+ UnoRuntime.queryInterface(
+ XIndexContainer.class,
+ xMenuElementFactory.createInstance("com.sun.star.ui.ActionTriggerContainer" ));
+
+ // initialize root menu entry "Help"
+ xRootMenuEntry.setPropertyValue( "Text", "Help" );
+ xRootMenuEntry.setPropertyValue( "CommandURL", "slot:5410" );
+ xRootMenuEntry.setPropertyValue( "HelpURL", "5410" );
+ xRootMenuEntry.setPropertyValue( "SubContainer", xSubMenuContainer );
+
+ // create menu entries for the new sub menu
+ // initialize help/content menu entry
+ // entry "Content"
+ XPropertySet xMenuEntry = UnoRuntime.queryInterface(
+ XPropertySet.class, xMenuElementFactory.createInstance(
+ "com.sun.star.ui.ActionTrigger" ));
+ xMenuEntry.setPropertyValue( "Text", "Content" );
+ xMenuEntry.setPropertyValue( "CommandURL", "slot:5401" );
+ xMenuEntry.setPropertyValue( "HelpURL", "5401" );
+
+ // insert menu entry to sub menu
+ xSubMenuContainer.insertByIndex( 0, xMenuEntry );
+
+ // initialize help/help on help
+ // entry "Help on Help"
+ xMenuEntry = UnoRuntime.queryInterface(
+ XPropertySet.class,
+ xMenuElementFactory.createInstance("com.sun.star.ui.ActionTrigger" ));
+ xMenuEntry.setPropertyValue("Text", "Help on Help");
+ xMenuEntry.setPropertyValue("CommandURL", "slot:5400");
+ xMenuEntry.setPropertyValue("HelpURL", "5400");
+
+ // insert menu entry to sub menu
+ xSubMenuContainer.insertByIndex( 1, xMenuEntry );
+ // initialize help/tips
+ // entry "Tips"
+ xMenuEntry = UnoRuntime.queryInterface(
+ XPropertySet.class,
+ xMenuElementFactory.createInstance("com.sun.star.ui.ActionTrigger" ));
+ xMenuEntry.setPropertyValue( "Text", "Tips" );
+ xMenuEntry.setPropertyValue( "CommandURL", "slot:5404" );
+ xMenuEntry.setPropertyValue( "HelpURL", "5404" );
+
+ // insert menu entry to sub menu
+ xSubMenuContainer.insertByIndex( 2, xMenuEntry );
+
+ // add separator into the given context menu
+ xContextMenu.insertByIndex( 1, xSeparator );
+
+ // add new sub menu into the given context menu
+ xContextMenu.insertByIndex( 1, xRootMenuEntry );
+
+ // The controller should execute the modified context menu and stop notifying other
+ // interceptors.
+ return ContextMenuInterceptorAction.EXECUTE_MODIFIED ;
+ }
+ } catch ( UnknownPropertyException ex ) {
+ // do something useful
+ // we used an unknown property
+ } catch ( IndexOutOfBoundsException ex ) {
+ // do something useful
+ // we used an invalid index for accessing a container
+ } catch ( Exception ex ) {
+ // something strange has happened!
+ } catch ( Throwable ex ) {
+ // catch java exceptions and do something useful
+ }
+
+ return ContextMenuInterceptorAction.IGNORED;
+ }
+}
diff --git a/qadevOOo/runner/helper/FileTools.java b/qadevOOo/runner/helper/FileTools.java
new file mode 100644
index 000000000..f8708e558
--- /dev/null
+++ b/qadevOOo/runner/helper/FileTools.java
@@ -0,0 +1,127 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package helper;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+
+/**
+ * This class deliver some functionality to copy files.
+ */
+public class FileTools {
+
+ /**
+ * Copies all files under srcDir to dstDir.
+ * If dstDir does not exist, it will be created.
+ * @param srcDir the source directory
+ * @param dstDir the destination directory
+ * @throws java.io.IOException throws java.io.IOException if something fails
+ */
+ public static void copyDirectory(File srcDir, File dstDir)
+ throws java.io.IOException {
+ copyDirectory(srcDir, dstDir, new String[]{});
+ }
+ /**
+ * Copies all files under srcDir to dstDir except Files given in the
+ * ignore list. This files will not be copied.
+ * If dstDir does not exist, it will be created.
+ * @param srcDir the source directory
+ * @param dstDir the destination directory
+ * @param ignore a list of files which should not be copied
+ * @throws java.io.IOException throws java.io.IOException if something fails
+ */
+ public static void copyDirectory(File srcDir, File dstDir, String[] ignore)
+ throws java.io.IOException {
+
+ for (int i=0; i<ignore.length;i++){
+ if (srcDir.getName().endsWith(ignore[i])) {
+ return;
+ }
+ }
+
+ if (srcDir.isDirectory()) {
+ if (!dstDir.exists()) {
+ if (!dstDir.mkdir()) {
+ throw new java.io.IOException("could not create folder " + dstDir);
+ }
+ }
+
+ String[] files = srcDir.list();
+ for (int i=0; i< files.length; i++) {
+ copyDirectory(new File(srcDir, files[i]), new File(dstDir, files[i]), ignore);
+ }
+ } else {
+ // This method is implemented in e1071 Copying a File
+ copyFile(srcDir, dstDir);
+ }
+ }
+
+ /**
+ * Copies src file to dst file. If the dst file does not exist, it is created
+ * @param src the source file
+ * @param dst the destination file
+ * @throws java.io.IOException throws java.io.IOException if something fails
+ */
+ public static void copyFile(File src, File dst) throws java.io.IOException {
+ InputStream in = null;
+ OutputStream out = null;
+ try {
+ in = new FileInputStream(src);
+ try {
+ out = new FileOutputStream(dst);
+
+ // Transfer bytes from in to out
+ byte[] buf = new byte[1024];
+ int len;
+ while ((len = in.read(buf)) > 0) {
+ out.write(buf, 0, len);
+ }
+ } finally {
+ if (out != null)
+ out.close();
+ }
+ } finally {
+ if (in != null)
+ in.close();
+ }
+ }
+
+
+ public static boolean cleanDir(File dir)
+ {
+ if (dir.isDirectory())
+ {
+ String[] children = dir.list();
+ for (int i=0; i<children.length; i++)
+ {
+ boolean success = cleanDir(new File(dir, children[i]));
+ if (!success)
+ {
+ return false;
+ }
+ }
+ }
+
+ // The directory is now empty so delete it
+ return dir.delete();
+ }
+}
diff --git a/qadevOOo/runner/helper/LoggingThread.java b/qadevOOo/runner/helper/LoggingThread.java
new file mode 100644
index 000000000..1bbfaea8c
--- /dev/null
+++ b/qadevOOo/runner/helper/LoggingThread.java
@@ -0,0 +1,80 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package helper;
+
+import share.*;
+import lib.TestParameters;
+import util.PropertyName;
+import util.utils;
+
+/**
+ * This class is printing to a <CODE>LogWriter</CODE>. This could be useful if a UNO-API
+ * function runs longer than time out. To avoid the assumption of death application
+ * a simple string is logged for 100 times of time out.</br>
+ * Example:</br>
+ * logger = new LoggingThread((LogWriter)log, tParam);
+ * logger.start();
+ * oObj.longRunningFunction();
+ * logger.finish();
+ *
+ */
+public class LoggingThread extends Thread {
+
+ private final TestParameters param;
+ private final LogWriter log;
+ private boolean finished = false;
+ private final boolean debug;
+
+ public LoggingThread(LogWriter log, TestParameters tParam) {
+ this.log = log;
+ this.param = tParam;
+ this.debug = tParam.getBool(PropertyName.DEBUG_IS_ACTIVE);
+ }
+
+ @Override
+ public void run() {
+ final int timeOut = param.getInt(PropertyName.TIME_OUT) / 2;
+ int count = 0;
+ finished = false;
+ if (debug) log.println("TimeOutLogger: " + utils.getDateTime() + " start");
+ while (!finished && count < 200) {
+ try {
+ if (debug) log.println("TimeOutLogger: "+utils.getDateTime() + count);
+ synchronized (this) {
+ wait(timeOut);
+ }
+ count++;
+ } catch (InterruptedException ex) {
+ }
+ }
+ if (debug) log.println("TimeOutLogger: " + utils.getDateTime() + " finished");
+ }
+
+ /**
+ * finished the LoggingThread
+ */
+ public void finish() {
+ finished = true;
+ synchronized (this) {
+ notify();
+ }
+ if (debug) log.println("TimeOutLogger: " + utils.getDateTime() + " try to finish ");
+ util.utils.pause(1000);
+ }
+}
diff --git a/qadevOOo/runner/helper/OSHelper.java b/qadevOOo/runner/helper/OSHelper.java
new file mode 100644
index 000000000..242647153
--- /dev/null
+++ b/qadevOOo/runner/helper/OSHelper.java
@@ -0,0 +1,50 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package helper;
+
+/**
+ * Helper object, to identify the current Operation System.
+ */
+public class OSHelper
+{
+ public static boolean isWindows()
+ {
+ return System.getProperty("os.name").toLowerCase().startsWith("windows");
+ }
+ public static boolean isSolarisIntel()
+ {
+ String sOSName = System.getProperty("os.name");
+ return ( sOSName.toLowerCase().startsWith("solaris") ||
+ sOSName.toLowerCase().startsWith("sunos") ) &&
+ System.getProperty("os.arch").equals("x86");
+ }
+ public static boolean isSolarisSparc()
+ {
+ String sOSName = System.getProperty("os.name");
+ return ( sOSName.toLowerCase().startsWith("solaris") ||
+ sOSName.toLowerCase().startsWith("sunos") ) &&
+ System.getProperty("os.arch").equals("sparc");
+ }
+ public static boolean isLinuxIntel()
+ {
+ return System.getProperty("os.name").toLowerCase().startsWith("linux") &&
+ System.getProperty("os.arch").equals("i386");
+ }
+
+}
diff --git a/qadevOOo/runner/helper/OfficeProvider.java b/qadevOOo/runner/helper/OfficeProvider.java
new file mode 100644
index 000000000..01599cd3f
--- /dev/null
+++ b/qadevOOo/runner/helper/OfficeProvider.java
@@ -0,0 +1,756 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package helper;
+
+import com.sun.star.beans.XFastPropertySet;
+import com.sun.star.bridge.XUnoUrlResolver;
+import com.sun.star.container.XEnumeration;
+import com.sun.star.container.XEnumerationAccess;
+import com.sun.star.frame.XDesktop;
+import com.sun.star.lang.XMultiComponentFactory;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.XComponentContext;
+import com.sun.star.util.XCloseable;
+import com.sun.star.util.XStringSubstitution;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+
+import lib.TestParameters;
+
+import share.DescEntry;
+import share.LogWriter;
+
+import util.DynamicClassLoader;
+import util.PropertyName;
+import util.utils;
+
+/**
+ * This class will connect the office and start it if possible
+ *
+ */
+public class OfficeProvider implements AppProvider
+{
+
+ private boolean debug = false;
+
+ /**
+ * copy the user layer to a safe place, usually to $TMP/user_backup$USER
+ */
+ private void backupUserLayer(TestParameters param, XMultiServiceFactory msf)
+ {
+ try
+ {
+ final XStringSubstitution sts = createStringSubstitution(msf);
+ debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
+
+ String userLayer = sts.getSubstituteVariableValue("$(user)");
+ userLayer = getDirSys(userLayer);
+ param.put("userLayer", userLayer);
+
+ final String copyLayer = util.utils.getUsersTempDir() + System.getProperty("file.separator") +
+ "user_backup" +
+ System.getProperty("user.name");
+ param.put("copyLayer", copyLayer);
+
+
+ dbg(" copy '" + userLayer + "' ->" + copyLayer + "'");
+ // Slow machines the copy job could spend some time. To avoid activating of OfficeWatcher it must be pinged
+ OfficeWatcherPing owp = new OfficeWatcherPing((OfficeWatcher) param.get(PropertyName.OFFICE_WATCHER));
+ owp.start();
+
+ deleteFilesAndDirector (new File(copyLayer));
+ FileTools.copyDirectory(new File(userLayer), new File(copyLayer), new String[]
+ {
+ "temp"
+ });
+
+ owp.finish();
+
+ }
+ catch (com.sun.star.container.NoSuchElementException e)
+ {
+ System.out.println("User Variable '$(user)' not defined.");
+ }
+ catch (com.sun.star.uno.Exception e)
+ {
+ System.out.println("Couldn't backup user layer");
+ e.printStackTrace();
+ }
+ catch (java.io.IOException e)
+ {
+ System.out.println("Couldn't backup user layer");
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Dispose the office.
+ * This method can only be used, if the office was connected in the first
+ * place: getManager() was called first.
+ * @return return true if desktop is terminates, else false
+ */
+ public boolean disposeManager(lib.TestParameters param)
+ {
+
+ XMultiServiceFactory msf = param.getMSF();
+
+ if (msf == null)
+ {
+ return true;
+ }
+ else
+ {
+ XDesktop desk = null;
+
+ try
+ {
+ desk = UnoRuntime.queryInterface(XDesktop.class, msf.createInstance("com.sun.star.frame.Desktop"));
+ }
+ catch (com.sun.star.uno.Exception ue)
+ {
+ return false;
+ }
+
+ msf = null;
+
+ if (desk != null)
+ {
+ desk.terminate();
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Method to get the ServiceManager of an Office
+ */
+ public Object getManager(lib.TestParameters param) throws UnsupportedEncodingException
+ {
+ String errorMessage = null;
+ boolean bAppExecutionHasWarning = false;
+ debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
+
+ String additionalArgs = (String) param.get(
+ "AdditionalConnectionArguments");
+
+ if (additionalArgs == null)
+ {
+ additionalArgs = ";";
+ }
+ else
+ {
+ additionalArgs = "," + additionalArgs + ";";
+ }
+
+ final String cncstr = "uno:" + param.get("ConnectionString") + ";urp" +
+ additionalArgs + "StarOffice.ServiceManager";
+
+ System.out.println("Connecting the Office with " + cncstr);
+
+ XMultiServiceFactory msf = connectOffice(cncstr);
+
+ // if the office is running and the office crashes while testing it could
+ // be useful to restart the office if possible and continuing the tests.
+ // Example: the UNO-API-Tests in the projects will be executed by calling
+ // 'damke'. This connects to an existing office. If the office crashes
+ // it is useful to restart the office and continuing the tests.
+ if ((param.getBool(util.PropertyName.AUTO_RESTART)) && (msf != null))
+ {
+ makeAppExecCommand(msf, param);
+ }
+
+ if (msf == null)
+ {
+ String exc = "";
+ Exception exConnectFailed = null;
+ boolean isExecutable = false;
+ boolean isAppKnown = ((cncstr.indexOf("host=localhost") > 0) || (cncstr.indexOf("pipe,name=") > 0));
+ isAppKnown &= ((String) param.get("AppExecutionCommand")).length() != 0;
+
+ if (isAppKnown)
+ {
+ dbg("Local Connection trying to start the Office");
+
+ //ensure that a pending officewatcher gets finished before a new
+ //office is started
+ final OfficeWatcher ow_old = (OfficeWatcher) param.get("Watcher");
+
+ if (ow_old != null)
+ {
+ ow_old.finish = true;
+ }
+
+ final String cmd = (String) param.get("AppExecutionCommand");
+ dbg("AppExecutionCommand: " + cmd);
+ // validate the AppExecutionCommand, but try it out anyway.
+ // keep the error message for later.
+ errorMessage =
+ util.utils.validateAppExecutionCommand(cmd, (String) param.get("OperatingSystem"));
+ if (errorMessage.startsWith("Error"))
+ {
+ System.out.println(errorMessage);
+ return null;
+ }
+ bAppExecutionHasWarning = !errorMessage.equals("OK");
+
+ final DynamicClassLoader dcl = new DynamicClassLoader();
+ final LogWriter log = (LogWriter) dcl.getInstance(
+ (String) param.get("LogWriter"));
+
+ //create empty entry
+ final DescEntry Entry = new DescEntry();
+ Entry.entryName = "office";
+ Entry.longName = "office";
+ Entry.EntryType = "placebo";
+ Entry.isOptional = false;
+ Entry.isToTest = false;
+ Entry.SubEntryCount = 0;
+ Entry.hasErrorMsg = false;
+ Entry.State = "non possible";
+ Entry.UserDefinedParams = param;
+
+ log.initialize(Entry, debug);
+
+ final ProcessHandler ph = new ProcessHandler(cmd, (PrintWriter) log);
+ isExecutable = ph.executeAsynchronously();
+
+ if (isExecutable)
+ {
+ param.put("AppProvider", ph);
+ final OfficeWatcher ow = new OfficeWatcher(param);
+ param.put("Watcher", ow);
+ ow.start();
+ ow.ping();
+ }
+
+ int k = 0;
+
+ // wait up to 21 seconds to get an office connection
+ while ((k < 42) && (msf == null))
+ {
+ try
+ {
+ msf = connect(cncstr);
+ }
+ catch (com.sun.star.uno.Exception ue)
+ {
+ exConnectFailed = ue;
+ exc = ue.getMessage();
+ }
+ catch (java.lang.Exception je)
+ {
+ exConnectFailed = je;
+ exc = je.getMessage();
+ }
+ if (msf == null)
+ {
+ util.utils.pause(500 * k);
+ }
+ k++;
+ }
+
+ if (msf == null)
+ {
+ System.out.println("Exception while connecting.\n" + exConnectFailed);
+ if (exc != null)
+ {
+ System.out.println(exc);
+ }
+ if (bAppExecutionHasWarning)
+ {
+ System.out.println(errorMessage);
+ }
+ }
+ else if (isExecutable)
+ {
+ backupUserLayer(param, msf);
+ }
+ }
+ else
+ {
+ System.out.println("Could not connect an Office and cannot start one.\n".concat("please start an office with following parameter:\n").
+ concat("\nsoffice --accept=").concat((String) param.get("ConnectionString")).concat(";urp;\n"));
+ }
+ }
+
+ return msf;
+ }
+
+ /**
+ * Connect an Office
+ * @param connectStr
+ * @return
+ * @throws com.sun.star.uno.Exception
+ * @throws com.sun.star.uno.RuntimeException
+ * @throws com.sun.star.connection.NoConnectException
+ * @throws Exception
+ */
+ private XMultiServiceFactory connect(String connectStr)
+ throws com.sun.star.uno.Exception,
+ com.sun.star.uno.RuntimeException,
+ com.sun.star.connection.NoConnectException,
+ Exception
+ {
+
+ // Get component context
+ final XComponentContext xcomponentcontext = com.sun.star.comp.helper.Bootstrap.createInitialComponentContext(null);
+
+ // initial serviceManager
+ final XMultiComponentFactory xLocalServiceManager = xcomponentcontext.getServiceManager();
+
+ // create a connector, so that it can contact the office
+ final Object xUrlResolver = xLocalServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", xcomponentcontext);
+ final XUnoUrlResolver urlResolver = UnoRuntime.queryInterface(XUnoUrlResolver.class, xUrlResolver);
+
+ final Object rInitialObject = urlResolver.resolve(connectStr);
+
+ XMultiServiceFactory xMSF = null;
+
+ if (rInitialObject != null)
+ {
+ // debug = true;
+ dbg("resolved url");
+
+ xMSF = UnoRuntime.queryInterface(XMultiServiceFactory.class, rInitialObject);
+ }
+
+ return xMSF;
+ }
+
+ /**
+ * Close an office.
+ * @param param The test parameters.
+ * @param closeIfPossible If true, close even if
+ * it was running before the test
+ */
+ public boolean closeExistingOffice(lib.TestParameters param, boolean closeIfPossible)
+ {
+
+ XMultiServiceFactory msf = param.getMSF();
+ final boolean alreadyConnected = (msf != null);
+ debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
+
+ if (alreadyConnected)
+ {
+ dbg("try to get ProcessHandler");
+
+ final ProcessHandler ph = (ProcessHandler) param.get("AppProvider");
+
+ if (ph != null)
+ {
+ dbg("ProcessHandler != null");
+
+ disposeOffice(msf, param);
+
+ // dispose watcher in case it's still running.
+ dbg("try to get OfficeWatcher");
+
+ final OfficeWatcher ow = (OfficeWatcher) param.get("Watcher");
+
+ if ((ow != null) && ow.isAlive())
+ {
+ dbg("OfficeWatcher will be finished");
+ ow.finish = true;
+ }
+ else
+ {
+ dbg("OfficeWatcher seems to be finished");
+ }
+
+ return true;
+ }
+ else
+ {
+ if (closeIfPossible)
+ {
+ return disposeOffice(msf, param);
+ }
+ }
+ }
+ else
+ {
+ final String cncstr = "uno:" + param.get("ConnectionString") +
+ ";urp;StarOffice.ServiceManager";
+ dbg("try to connect office");
+ msf = connectOffice(cncstr);
+
+ if (closeIfPossible)
+ {
+ return disposeOffice(msf, param);
+ }
+ }
+ dbg("closeExistingOffice finished");
+ return true;
+ }
+
+ private XMultiServiceFactory connectOffice(String cncstr)
+ {
+ XMultiServiceFactory msf = null;
+ String exc = "";
+ // debug = true;
+
+ dbg("trying to connect to " + cncstr);
+
+ try
+ {
+ msf = connect(cncstr);
+ }
+ catch (com.sun.star.uno.Exception ue)
+ {
+ exc = ue.getMessage();
+ }
+ catch (java.lang.Exception je)
+ {
+ exc = je.getMessage();
+ }
+
+ if (debug && exc != null && exc.length() != 0)
+ {
+ dbg("Could not connect an Office. " + exc);
+ }
+
+ return msf;
+ }
+
+ private boolean disposeOffice(XMultiServiceFactory msf,
+ TestParameters param)
+ {
+ XDesktop desk = null;
+
+ debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
+
+ boolean result = true;
+
+ if (msf != null)
+ {
+
+ // disable QuickStarter
+ try
+ {
+ Object quickStarter = msf.createInstance("com.sun.star.office.Quickstart");
+ XFastPropertySet fps = UnoRuntime.queryInterface(XFastPropertySet.class, quickStarter);
+ fps.setFastPropertyValue(0, false);
+ }
+ catch (com.sun.star.uno.Exception ex)
+ {
+ dbg("ERROR: Could not disable QuickStarter: " + ex.toString());
+ }
+
+ try
+ {
+ desk = UnoRuntime.queryInterface(XDesktop.class, msf.createInstance("com.sun.star.frame.Desktop"));
+ msf = null;
+
+ if (desk != null)
+ {
+ final boolean allClosed = closeAllWindows(desk);
+
+ if (!allClosed)
+ {
+ dbg("Couldn't close all office windows!");
+ }
+
+ dbg("Trying to terminate the desktop");
+
+ desk.terminate();
+ dbg("Desktop terminated");
+ }
+ }
+ catch (com.sun.star.uno.Exception ue)
+ {
+ result = false;
+ }
+ catch (com.sun.star.lang.DisposedException ue)
+ {
+ result = false;
+ }
+ }
+
+ final ProcessHandler ph = (ProcessHandler) param.get("AppProvider");
+
+ if (ph != null)
+ {
+ // dispose watcher in case it's still running.
+ final OfficeWatcher ow = (OfficeWatcher) param.get("Watcher");
+
+ if ((ow != null) && ow.isAlive())
+ {
+ ow.finish = true;
+ }
+
+ ph.kill();
+ }
+
+ param.remove("AppProvider");
+ param.remove("ServiceFactory");
+
+ //copy user_backup into user layer
+ try
+ {
+ final String userLayer = (String) param.get("userLayer");
+ final String copyLayer = (String) param.get("copyLayer");
+ if (userLayer != null && copyLayer != null)
+ {
+ deleteFilesAndDirector(new File(userLayer));
+ final File copyFile = new File(copyLayer);
+ dbg("copy '" + copyFile + "' -> '" + userLayer + "'");
+ FileTools.copyDirectory(copyFile, new File(userLayer), new String[]
+ {
+ "temp"
+ });
+ dbg("copy '" + copyFile + "' -> '" + userLayer + "' finished");
+
+ // remove all user_backup folder in temp dir
+ // this is for the case the runner was killed and some old backup folder still stay in temp dir
+
+
+ }
+ else
+ {
+ System.out.println("Cannot copy layer: '" + copyLayer + "' back to user layer: '" + userLayer + "'");
+ }
+ }
+ catch (java.io.IOException e)
+ {
+ dbg("Couldn't recover from backup\n" + e.getMessage());
+ }
+ return result;
+ }
+
+ private boolean closeAllWindows(XDesktop desk)
+ {
+ final XEnumerationAccess compEnumAccess = desk.getComponents();
+ final XEnumeration compEnum = compEnumAccess.createEnumeration();
+ boolean res = true;
+
+ try
+ {
+ while (compEnum.hasMoreElements())
+ {
+ final XCloseable closer = UnoRuntime.queryInterface(XCloseable.class, compEnum.nextElement());
+
+ if (closer != null)
+ {
+ closer.close(true);
+ }
+ }
+ }
+ catch (com.sun.star.util.CloseVetoException cve)
+ {
+ res = false;
+ }
+ catch (com.sun.star.container.NoSuchElementException nsee)
+ {
+ res = false;
+ }
+ catch (com.sun.star.lang.WrappedTargetException wte)
+ {
+ res = false;
+ }
+
+ return res;
+ }
+
+ private static XStringSubstitution createStringSubstitution(XMultiServiceFactory xMSF) throws com.sun.star.uno.Exception
+ {
+ Object xPathSubst = xMSF.createInstance(
+ "com.sun.star.util.PathSubstitution");
+ return UnoRuntime.queryInterface(XStringSubstitution.class, xPathSubst);
+ }
+
+ /**
+ * converts directory without 'file:///' prefix.
+ * and System dependent file separator
+ */
+ private static String getDirSys(String dir)
+ {
+ String sysDir = "";
+
+ final int idx = dir.indexOf("file://");
+
+ final int idx2 = dir.indexOf("file:///");
+
+ // remove leading 'file://'
+ if (idx < 0)
+ {
+ sysDir = dir;
+ }
+ else
+ {
+ sysDir = dir.substring("file://".length());
+ }
+
+ sysDir = sysDir.replace("%20", " ");
+
+ // append '/' if not there (e.g. linux)
+ if (sysDir.charAt(sysDir.length() - 1) != '/')
+ {
+ sysDir += "/";
+ }
+
+ // remove leading '/' and replace others with '\' on windows machines
+ final String sep = System.getProperty("file.separator");
+
+ if (sep.equalsIgnoreCase("\\"))
+ {
+ if (idx2 >= 0)
+ {
+ sysDir = sysDir.substring(1);
+ }
+ else
+ {
+ //network path
+ sysDir = "//" + sysDir;
+ }
+ sysDir = sysDir.replace('/', '\\');
+ }
+
+ return sysDir;
+ }
+
+ /**
+ * If the office is connected but the <CODE>AppExecutionCommand</CODE> is not set,
+ * this function asks the office for its location and fill the
+ * <CODE>AppExecutionCommand</CODE> with valid content.
+ * This function was only called if parameter <CODE>AutoRestart</CODE> is set.
+ * @param msf the <CODE>MultiServiceFactory</CODE>
+ * @param param the <CODE>TestParameters</CODE>
+ */
+ private void makeAppExecCommand(XMultiServiceFactory msf, TestParameters param)
+ {
+ debug = param.getBool(PropertyName.DEBUG_IS_ACTIVE);
+
+ // get existing AppExecutionCommand if available, else empty string
+ String command = (String) param.get(util.PropertyName.APP_EXECUTION_COMMAND);
+
+ String connectionString;
+ if (param.getBool(util.PropertyName.USE_PIPE_CONNECTION))
+ {
+ // This is the default behaviour
+ connectionString = (String) param.get(util.PropertyName.PIPE_CONNECTION_STRING);
+ }
+ else
+ {
+ // is used if UsePipeConnection=false
+ connectionString = (String) param.get(util.PropertyName.CONNECTION_STRING);
+ }
+
+ String sysBinDir = "";
+
+ try
+ {
+ sysBinDir = utils.getSystemURL(utils.expandMacro(msf, "$SYSBINDIR"));
+ }
+ catch (java.lang.Exception e)
+ {
+ dbg("could not get system binary directory");
+ return;
+ }
+
+ // does the existing command show to the connected office?
+ if (command.indexOf(sysBinDir) == -1)
+ {
+ command = sysBinDir + System.getProperty("file.separator") + "soffice" +
+ " --norestore --accept=" + connectionString + ";urp;";
+ }
+
+ dbg("update AppExecutionCommand: " + command);
+
+ param.put(util.PropertyName.APP_EXECUTION_COMMAND, command);
+ }
+
+ private void dbg(String message)
+ {
+ if (debug)
+ {
+ System.out.println(utils.getDateTime() + "OfficeProvider: " + message);
+ }
+
+ }
+
+ private static class OfficeWatcherPing extends Thread
+ {
+
+ private final OfficeWatcher ow;
+ private boolean bStop = false;
+
+ public OfficeWatcherPing(OfficeWatcher ow)
+ {
+ this.ow = ow;
+ }
+
+ @Override
+ public void run()
+ {
+ System.out.println(utils.getDateTime() + "OfficeProvider:Owp: start ");
+
+ while (!bStop)
+ {
+ System.out.println(utils.getDateTime() + "OfficeProvider:Owp: ping ");
+ ow.ping();
+ System.out.println(utils.getDateTime() + "OfficeProvider:Owp: sleep ");
+ util.utils.pause(1000);
+ }
+
+ }
+
+ public void finish()
+ {
+ synchronized(this)
+ {
+ bStop = true;
+ System.out.println(utils.getDateTime() + "OfficeProvider:Owp: stop ");
+
+ notify();
+ }
+ }
+ }
+
+ private void deleteFilesAndDirector(File file)
+ {
+ File f = file;
+ if(f.isDirectory())
+ {
+ File files[] = f.listFiles();
+ int filesLength = files != null ? files.length : 0;
+ for(int i = 0; i < filesLength; ++i)
+ {
+ deleteFilesAndDirector(files[i]);
+ }
+ boolean bDeleteOk = f.delete();
+ if (!bDeleteOk) {
+ System.out.println("delete failed");
+ }
+ }
+ else if (f.isFile())
+ {
+ boolean bDeleteOk = f.delete();
+ if (!bDeleteOk) {
+ System.out.println("delete failed");
+ }
+ }
+ }
+}
diff --git a/qadevOOo/runner/helper/OfficeWatcher.java b/qadevOOo/runner/helper/OfficeWatcher.java
new file mode 100644
index 000000000..924a9e4af
--- /dev/null
+++ b/qadevOOo/runner/helper/OfficeWatcher.java
@@ -0,0 +1,93 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package helper;
+
+import lib.TestParameters;
+import util.utils;
+
+public class OfficeWatcher extends Thread implements share.Watcher {
+
+ public boolean finish;
+ private final TestParameters params;
+ private int StoredPing = 0;
+ private final boolean debug;
+
+ public OfficeWatcher(TestParameters param) {
+ this.finish = false;
+ this.params = param;
+ this.debug = params.getBool(util.PropertyName.DEBUG_IS_ACTIVE);
+ }
+
+ /**
+ * pings the office watcher to check for changes
+ */
+ public void ping() {
+ try {
+ StoredPing++;
+ } catch (Exception e) {
+ StoredPing = 0;
+ }
+ }
+
+ /**
+ * returns the amount of pings
+ * @return returns the amount of pings
+ */
+ public int getPing() {
+ return StoredPing;
+ }
+
+ @Override
+ public void run() {
+ dbg("started");
+ boolean isDone = false;
+ final ProcessHandler ph = (ProcessHandler) params.get("AppProvider");
+ int timeOut = params.getInt("TimeOut");
+ if (ph == null) {
+ isDone = true;
+ }
+ while (!isDone) {
+ timeOut = params.getInt("TimeOut");
+ final int previous = StoredPing;
+ util.utils.pause(timeOut == 0 ? 30000 : timeOut);
+ // a timeout with value 0 lets watcher not react.
+ if ((StoredPing == previous) && timeOut != 0) {
+ isDone = true;
+ }
+ // execute in case the watcher is not needed anymore
+ if (finish) {
+ return;
+ }
+ }
+ if (ph != null) {
+ dbg("the Office is idle for " + timeOut / 1000 +
+ " seconds, it probably hangs and is killed NOW.");
+ ph.kill();
+ } else {
+ dbg("reached timeout but ProcessHandler is NULL");
+ }
+ util.utils.pause(timeOut == 0 ? 30000 : timeOut);
+ dbg("finished");
+ }
+
+ private void dbg(String message) {
+ if (debug) {
+ System.out.println(utils.getDateTime() + "OfficeWatcher: " + message);
+ }
+ }
+}
diff --git a/qadevOOo/runner/helper/ProcessHandler.java b/qadevOOo/runner/helper/ProcessHandler.java
new file mode 100644
index 000000000..49aba431a
--- /dev/null
+++ b/qadevOOo/runner/helper/ProcessHandler.java
@@ -0,0 +1,400 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package helper;
+
+import java.io.InputStream;
+import java.io.File;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+import java.io.PrintWriter;
+import java.io.PrintStream;
+import java.io.LineNumberReader;
+import java.io.InputStreamReader;
+import lib.TestParameters;
+import util.PropertyName;
+import util.utils;
+
+/*
+ * Class collect information from input stream in
+ * background (separate thread) and outputs it to
+ * some log stream. I helps to avoid buffer overflow
+ * when output stream has small buffer size (e.g.
+ * in case when handling stdout from external
+ * <code>Process</code>)
+ *
+ * This class is currently used by ProcessHandler
+ * internally only.
+ */
+class Pump extends Thread
+{
+
+ private final LineNumberReader reader;
+ private final String pref;
+ private final StringBuffer buf = new StringBuffer(256);
+ private final PrintWriter log;
+ private final boolean bOutput;
+
+ /**
+ * Creates Pump for specified <code>InputStream</code>.
+ * This Pump also synchronously output text read to
+ * log by prefixed lines. Constructor immediately
+ * starts reading in a separate thread.
+ *
+ * @param is Stream which requires permanent reading.
+ * @param log Writer where prefixed text lines to be output
+ * @param outPrefix A prefix which is printed at the
+ * beginning of each output line.
+ */
+ public Pump(InputStream is, PrintWriter log, String outPrefix, boolean _bOutput)
+ {
+ this.pref = (outPrefix == null) ? "" : outPrefix;
+ reader = new LineNumberReader(new InputStreamReader(is));
+ this.log = log;
+ this.bOutput = _bOutput;
+ start();
+ }
+
+ @Override
+ public void run()
+ {
+ try
+ {
+ String line = reader.readLine();
+ while (line != null)
+ {
+ if (bOutput)
+ {
+ log.println(pref + line);
+ log.flush();
+ }
+ buf.append(line).append('\n');
+ line = reader.readLine();
+ }
+ }
+ catch (java.io.IOException e)
+ {
+ log.println(pref + "Exception occurred: " + e);
+ }
+ }
+
+ /**
+ * Returns the text collected from input stream.
+ */
+ public String getStringBuffer()
+ {
+ return buf.toString();
+ }
+}
+
+/**
+ * Class provides convenient way for running external program
+ * handle its standard streams, control execution and check results.
+ * Instance of this class must be created only for a single
+ * execution. If you need to execute the same command again you
+ * should create a new instance for this.
+ */
+public class ProcessHandler
+{
+ private String cmdLine;
+ private String[] envVars = null;
+ private File workDir = null;
+ private PrintWriter log;
+ private int exitValue = -1;
+ private boolean isFinished = false;
+ private boolean isStarted = false;
+ private PrintStream stdIn = null;
+ private Process m_aProcess = null;
+ private boolean debug = false;
+ private boolean bUseOutput = true;
+
+ private int m_nProcessTimeout = 0;
+ private ProcessWatcher m_aWatcher;
+
+ /**
+ * Creates instance with specified external command and
+ * log stream where debug info and output
+ * of external command is printed out.
+ */
+ public ProcessHandler(String cmdLine, PrintWriter log) throws UnsupportedEncodingException
+ {
+ this(cmdLine, log, null, null);
+ }
+
+ /**
+ * Creates instance with specified external command which
+ * will be executed in the same work directory and
+ *
+ * @param cmdLine the command to be executed
+ * @param log log stream where debug info and output
+ * of external command is printed .
+ * @param workDir The working directory of the new process
+ * @param envVars The specified environment variables are
+ * set for the new process.
+ * If log stream is null, logging is printed to stdout.
+ * @param timeOut When started synchronously, the maximum time the
+ * process will live. When the process being destroyed
+ * a log will be written out. It can be asked on
+ * <code>isTimedOut()</code> if it has been terminated.
+ *
+ * timeOut > 0
+ * Waits specified time in milliSeconds for
+ * process to exit and return its status.
+ *
+ * timeOut = 0
+ * Waits for the process to end regularly
+ *
+ */
+ private ProcessHandler(String cmdLine, PrintWriter log, File workDir, String[] envVars) throws UnsupportedEncodingException
+ {
+ this.cmdLine = cmdLine;
+ this.workDir = workDir;
+ this.log = log;
+ this.envVars = envVars;
+ if (log == null)
+ {
+ this.log = new PrintWriter(new OutputStreamWriter(System.out, "UTF-8"));
+ }
+ else
+ {
+ this.log = log;
+ }
+ }
+
+ /**
+ * Executes the command immediately returns. The process
+ * remains in running state.
+ *
+ * @return <code>true</code> if process was successfully
+ * started.
+ */
+ public boolean executeAsynchronously()
+ {
+ execute();
+ return isStarted();
+ }
+
+ public synchronized void kill()
+ {
+ if (!isStarted())
+ {
+ return;
+ }
+ boolean exit = false;
+ int counter = 1;
+ while (counter < 3 && !exit)
+ {
+ m_aProcess.destroy();
+
+ util.utils.pause(1000 * counter);
+ try
+ {
+ final int exit_Value = m_aProcess.exitValue();
+ if (exit_Value < 1)
+ {
+ exit = true;
+ }
+ else
+ {
+ counter++;
+ }
+ dbg("kill: process closed with exit code " + exit_Value);
+ }
+ catch (java.lang.IllegalThreadStateException e)
+ {
+ if (counter < 3)
+ {
+ dbg("kill: Couldn't close process after " + counter + " attempts, trying again");
+ }
+ counter++;
+ }
+ }
+ isStarted = false;
+ }
+
+ private void showEnvVars()
+ {
+ if (envVars != null)
+ {
+ for (int i = 0; i < envVars.length; i++)
+ {
+ log.println("env: " + envVars[i]);
+ }
+ }
+ else
+ {
+ log.println("env: null");
+ }
+ }
+
+ private void execute()
+ {
+ if (isStarted())
+ {
+ throw new RuntimeException(
+ "The process handler has already been executed.");
+ }
+ final Runtime runtime = Runtime.getRuntime();
+ try
+ {
+ if (workDir != null)
+ {
+ log.println(utils.getDateTime() + "execute: Starting command: ");
+ log.println(cmdLine + " path=" + workDir.getAbsolutePath());
+ showEnvVars();
+ m_aProcess = runtime.exec(cmdLine, envVars, workDir);
+ }
+ else
+ {
+ log.println(utils.getDateTime() + "execute: Starting command: ");
+ log.println(cmdLine);
+ showEnvVars();
+ m_aProcess = runtime.exec(cmdLine, envVars);
+ }
+ isStarted = true;
+ }
+ catch (java.io.IOException e)
+ {
+ log.println(utils.getDateTime() + "execute: The command " + cmdLine + " can't be started: " + e);
+ return;
+ }
+ dbg("execute: pump io-streams");
+ new Pump(m_aProcess.getInputStream(), log, "out > ", bUseOutput);
+ new Pump(m_aProcess.getErrorStream(), log, "err > ", bUseOutput);
+ stdIn = new PrintStream(m_aProcess.getOutputStream());
+
+ dbg("execute: flush io-streams");
+
+ flushInput();
+ }
+
+ private void flushInput()
+ {
+ if (stdIn == null)
+ {
+ return;
+ }
+
+ synchronized(this)
+ {
+ stdIn.flush();
+ }
+ }
+
+ /**
+ * Returns information about was the command started or
+ * not.
+ *
+ * @return <code>true</code> if the external command was
+ * found and successfully started.
+ */
+ private boolean isStarted()
+ {
+ return isStarted;
+ }
+
+ /**
+ * Returns the information about the final state of command
+ * execution.
+ *
+ * @return <code>true</code> if the command correctly starts,
+ * exits and was not interrupted due to timeout.
+ */
+ private boolean isFinished()
+ {
+ return isFinished;
+ }
+
+ /**
+ * Returns exit code of the external command.
+ *
+ * @return exit code of command if it was finished,
+ * -1 if not.
+ */
+ public int getExitCode()
+ {
+ try
+ {
+ exitValue = m_aProcess.exitValue();
+ }
+ catch (Exception e)
+ {
+ }
+
+ return exitValue;
+ }
+
+ private void dbg(String message)
+ {
+ if (debug)
+ {
+ log.println(utils.getDateTime() + "PH." + message);
+ }
+ }
+
+ private static class ProcessWatcher extends Thread
+ {
+
+ private int m_nTimeoutInSec;
+ private final boolean m_bInterrupt;
+
+ private ProcessWatcher(int _nTimeOut)
+ {
+ m_nTimeoutInSec = _nTimeOut;
+ m_bInterrupt = false;
+ }
+
+ /**
+ * returns true, if the thread should hold on
+ */
+ public synchronized boolean isInHoldOn()
+ {
+ return m_bInterrupt;
+ }
+ @Override
+ public void run()
+ {
+ while (m_nTimeoutInSec > 0)
+ {
+ m_nTimeoutInSec--;
+ util.utils.pause(1000);
+ if (isInHoldOn())
+ {
+ break;
+ }
+ }
+ }
+
+ }
+
+ /**
+ * If the timeout only given by setProcessTimeout(int seconds) function is != 0,
+ * an extra thread is created and after time has run out, the ProcessKiller string
+ * given by function setProcessKiller(string) will execute.
+ * So it is possible to kill a running office after a given time of seconds.
+ */
+ private void initializeProcessKiller()
+ {
+ if (m_nProcessTimeout != 0)
+ {
+ m_aWatcher = new ProcessWatcher(m_nProcessTimeout);
+ m_aWatcher.start();
+ }
+ }
+
+
+}
diff --git a/qadevOOo/runner/helper/PropertyHandlerFactroy.java b/qadevOOo/runner/helper/PropertyHandlerFactroy.java
new file mode 100644
index 000000000..74f16d867
--- /dev/null
+++ b/qadevOOo/runner/helper/PropertyHandlerFactroy.java
@@ -0,0 +1,35 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package helper;
+
+import com.sun.star.lang.XSingleComponentFactory;
+
+public class PropertyHandlerFactroy implements XSingleComponentFactory{
+
+ public Object createInstanceWithArgumentsAndContext(Object[] obj, com.sun.star.uno.XComponentContext xComponentContext)
+ throws com.sun.star.uno.Exception {
+ return new PropertyHandlerImpl();
+ }
+
+ public Object createInstanceWithContext(com.sun.star.uno.XComponentContext xComponentContext)
+ throws com.sun.star.uno.Exception {
+ return new PropertyHandlerImpl();
+ }
+
+}
diff --git a/qadevOOo/runner/helper/PropertyHandlerImpl.java b/qadevOOo/runner/helper/PropertyHandlerImpl.java
new file mode 100644
index 000000000..a00eee233
--- /dev/null
+++ b/qadevOOo/runner/helper/PropertyHandlerImpl.java
@@ -0,0 +1,234 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package helper;
+
+import com.sun.star.inspection.LineDescriptor;
+import com.sun.star.inspection.XPropertyHandler;
+
+/**
+ * This implementation of <CODE>PropertyHandler</CODE> does currently nothing.
+ * All methods are implemented, but not filled with content.
+ * @see com.sun.star.inspection.XPropertyHandler
+ */
+public class PropertyHandlerImpl implements XPropertyHandler{
+
+ /**
+ * This method currently does nothing
+ * @param ActuatingPropertyName the id of the actuating property.
+ * @param NewValue the new value of the property
+ * @param OldValue the old value of the property
+ * @param InspectorUI a callback for updating the object inspector UI
+ * @param FirstTimeInit If true , the method is called for the first-time update of the respective property, that is, when the property browser is just initializing with the properties of the introspected object.
+ * If false , there was a real ::com::sun::star::beans::XPropertyChangeListener::propertyChange event which triggered the call.
+ *
+ * In some cases it may be necessary to differentiate between both situations. For instance, if you want to set the value of another property when an actuating property's value changed, you should definitely not do this when FirstTimeInit is true .
+ * @throws com.sun.star.lang.NullPointerException ::com::sun::star::lang::NullPointerException if InspectorUI is NULL
+ */
+ public void actuatingPropertyChanged(
+ String ActuatingPropertyName,
+ Object NewValue,
+ Object OldValue,
+ com.sun.star.inspection.XObjectInspectorUI InspectorUI,
+ boolean FirstTimeInit)
+ throws com.sun.star.lang.NullPointerException {
+ }
+
+ /**
+ * This method currently does nothing
+ * @param xEventListener the listener to notify about changes
+ */
+ public void addEventListener(com.sun.star.lang.XEventListener xEventListener) {
+ }
+
+ /**
+ * This method currently does nothing
+ * @param xPropertyChangeListener the listener to notify about property changes
+ * @throws com.sun.star.lang.NullPointerException com::sun::star::lang::NullPointerException if the listener is NULL
+ */
+ public void addPropertyChangeListener(com.sun.star.beans.XPropertyChangeListener xPropertyChangeListener) throws com.sun.star.lang.NullPointerException {
+ }
+
+ /**
+ * This method currently does nothing
+ * @param PropertyName The name of the property whose value is to be converted.
+ * @param PropertyValue The to-be-converted property value.
+ * @param ControlValueType The target type of the conversion. This type is determined by the control which is used to display the property, which in turn is determined by the handler itself in describePropertyLine .
+ * Speaking strictly, this is passed for convenience only, since every XPropertyHandler implementation should know exactly which type to expect, since it implicitly determined this type in describePropertyLine by creating an appropriate XPropertyControl .
+ *
+ * @throws com.sun.star.beans.UnknownPropertyException ::com::sun::star::beans::UnknownPropertyException if the given property is not supported by the property handler
+ * @return null
+ */
+ public Object convertToControlValue(
+ String PropertyName,
+ Object PropertyValue,
+ com.sun.star.uno.Type ControlValueType)
+ throws com.sun.star.beans.UnknownPropertyException {
+ return null;
+ }
+
+ /**
+ * This method currently does nothing
+ * @param PropertyName The name of the conversion's target property.
+ * @param ControlValue The to-be-converted control value. This value has been obtained from an XPropertyControl , using its Value attribute.
+ * @throws com.sun.star.beans.UnknownPropertyException ::com::sun::star::beans::UnknownPropertyException if the given property is not supported by the property handler
+ * @return null
+ */
+ public Object convertToPropertyValue(String PropertyName, Object ControlValue) throws com.sun.star.beans.UnknownPropertyException {
+ return null;
+ }
+
+ /**
+ * This method currently does nothing
+ * @param PropertyName the name of the property whose user interface is to be described
+ * @param ControlFactory a factory for creating XPropertyControl instances. Must not be NULL .
+ * @throws com.sun.star.beans.UnknownPropertyException ::com::sun::star::beans::UnknownPropertyException if the given property is not supported by this handler
+ * @throws com.sun.star.lang.NullPointerException ::com::sun::star::lang::NullPointerException if ControlFactory is NULL .
+ */
+ public LineDescriptor describePropertyLine(
+ String PropertyName,
+ com.sun.star.inspection.XPropertyControlFactory ControlFactory)
+ throws com.sun.star.beans.UnknownPropertyException,
+ com.sun.star.lang.NullPointerException {
+ return null;
+ }
+
+ /**
+ * This method currently does nothing
+ */
+ public void dispose() {
+ }
+
+ /**
+ * This method currently does nothing
+ * @return null
+ */
+ public String[] getActuatingProperties() {
+ return null;
+ }
+
+ /**
+ * This method currently does nothing
+ * @param PropertyName the name of the property whose state is to be retrieved
+ * @throws com.sun.star.beans.UnknownPropertyException ::com::sun::star::beans::UnknownPropertyException if the given property is not supported by the property handler
+ * @return null
+ */
+ public com.sun.star.beans.PropertyState getPropertyState(String PropertyName)
+ throws com.sun.star.beans.UnknownPropertyException {
+ return null;
+ }
+
+ /**
+ * This method currently does nothing
+ * @param PropertyName the name of the property whose value is to be retrieved
+ * @throws com.sun.star.beans.UnknownPropertyException ::com::sun::star::beans::UnknownPropertyException if the given property is not supported by the property handler
+ * @return null
+ */
+ public Object getPropertyValue(String PropertyName) throws com.sun.star.beans.UnknownPropertyException {
+ return null;
+ }
+
+ /**
+ * This method currently does nothing
+ * @return null
+ */
+ public String[] getSupersededProperties() {
+ return null;
+ }
+
+ /**
+ * This method currently does nothing
+ * @return null
+ */
+ public com.sun.star.beans.Property[] getSupportedProperties() {
+ return null;
+ }
+
+ /**
+ * This method currently does nothing
+ * @param Component the component to inspect. Must not be NULL
+ * @throws com.sun.star.lang.NullPointerException com::sun::star::lang::NullPointerException if the component is NULL
+ */
+ public void inspect(Object Component) throws com.sun.star.lang.NullPointerException {
+ }
+
+ /**
+ * This method currently does nothing
+ * @param PropertyName the name of the property whose composability is to be determined
+ * @throws com.sun.star.beans.UnknownPropertyException ::com::sun::star::beans::UnknownPropertyException if the given property is not supported by the property handler
+ *
+ *
+ * @return null
+ */
+ public boolean isComposable(String PropertyName) throws com.sun.star.beans.UnknownPropertyException {
+ return false;
+ }
+
+ /**
+ * This method currently does nothing
+ * @param PropertyName The name of the property whose browse button has been clicked
+ * @param Primary true if and only if the primary button has been clicked, false otherwise
+ * @param out_Data If the method returns InteractiveSelectionResult::ObtainedValue , then _rData contains the value which has been interactively obtained from the user, and which still needs to be set at the inspected component.
+ * @param InspectorUI provides access to the object inspector UI. Implementations should use this if the property selection requires non-modal user input. In those cases, onInteractivePropertySelection should return InteractiveSelectionResult::Pending , and the UI for (at least) the property whose input is still pending should be disabled.
+ *
+ * @throws com.sun.star.beans.UnknownPropertyException ::com::sun::star::beans::UnknownPropertyException if the given property is not supported by the property handler
+ * @throws com.sun.star.lang.NullPointerException ::com::sun::star::lang::NullPointerException if InspectorUI is NULL
+ * @return null
+ */
+ public com.sun.star.inspection.InteractiveSelectionResult onInteractivePropertySelection(
+ String PropertyName,
+ boolean Primary,
+ Object[] out_Data,
+ com.sun.star.inspection.XObjectInspectorUI InspectorUI)
+ throws com.sun.star.beans.UnknownPropertyException,
+ com.sun.star.lang.NullPointerException {
+ return null;
+ }
+
+ /**
+ * This method currently does nothing
+ * @param xEventListener the listener to be revoked
+ */
+ public void removeEventListener(com.sun.star.lang.XEventListener xEventListener) {
+ }
+
+ /**
+ * This method currently does nothing
+ * @param xPropertyChangeListener the listener to be revoke
+ */
+ public void removePropertyChangeListener(com.sun.star.beans.XPropertyChangeListener xPropertyChangeListener) {
+ }
+
+ /**
+ * This method currently does nothing
+ * @param PropertyName the name of the property whose value is to be set
+ * @param Value the property value to set
+ * @throws com.sun.star.beans.UnknownPropertyException ::com::sun::star::beans::UnknownPropertyException if the given property is not supported by the property handler
+ */
+ public void setPropertyValue(String PropertyName, Object Value) throws com.sun.star.beans.UnknownPropertyException {
+ }
+
+ /**
+ * This method currently does nothing
+ * @param Suspend Whether the handler is to be suspended true or reactivated ( false ). The latter happens if a handler was successfully suspended, but an external instance vetoed the whole suspension process.
+ * @return false
+ */
+ public boolean suspend(boolean Suspend) {
+ return false;
+ }
+
+}
diff --git a/qadevOOo/runner/helper/StreamSimulator.java b/qadevOOo/runner/helper/StreamSimulator.java
new file mode 100644
index 000000000..8e17e910b
--- /dev/null
+++ b/qadevOOo/runner/helper/StreamSimulator.java
@@ -0,0 +1,394 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package helper;
+
+import com.sun.star.uno.UnoRuntime;
+
+
+import com.sun.star.ucb.XSimpleFileAccess;
+
+/**
+ * It simulates an input and output stream and
+ * implements the interfaces XInputStream, XOutputStream.
+ * So it can be used for testing loading/saving of documents
+ * using streams instead of URLs.
+ *
+ */
+public class StreamSimulator implements com.sun.star.io.XInputStream ,
+ com.sun.star.io.XOutputStream ,
+ com.sun.star.io.XSeekable
+{
+
+ /**
+ * @member m_sFileName name of the corresponding file on disk
+ * @member m_xInStream the internal input stream for reading
+ * @member m_xOutStream the internal input stream for writing
+ * @member m_xSeek points at runtime to m_xInStream or m_xOutStream and make it seekable
+ *
+ * @member //m_aProtocol the external set protocol object for logging messages
+ * @member m_bInWasUsed indicates, that the input stream interface was used
+ * @member m_bOutWasUsed indicates, that the output stream interface was used
+ */
+
+ private com.sun.star.io.XInputStream m_xInStream ;
+ private com.sun.star.io.XOutputStream m_xOutStream ;
+ private com.sun.star.io.XSeekable m_xSeek ;
+
+
+
+
+
+ /**
+ * construct a new instance of this class
+ * It set the name of the corresponding file on disk, which
+ * should be source or target for the following operations on
+ * this object. And it regulate if it should function as
+ * input or output stream.
+ *
+ * @param sFileName
+ * name of the file on disk
+ * Will be used as source (if param bInput==true)
+ * or as target (if param bInput==false).
+ *
+ * @param bInput
+ * it specify, which interface should work at this object.
+ * <TRUE/> => we simulate an input stream
+ * <FALSE/> => we simulate an output stream
+ *
+ * @throw com.sun.star.io.NotConnectedException
+ * in case the internal streams to the file on disk couldn't established.
+ * They are necessary. Otherwise this simulator can't really work.
+ */
+ public StreamSimulator( String sFileName , boolean bInput ,
+ lib.TestParameters param ) throws com.sun.star.io.NotConnectedException
+ {
+ try
+ {
+ XSimpleFileAccess xHelper = UnoRuntime.queryInterface(XSimpleFileAccess.class,
+ param.getMSF().createInstance("com.sun.star.ucb.SimpleFileAccess"));
+
+ if (xHelper == null)
+ throw new com.sun.star.io.NotConnectedException("ucb helper not available. Can't create streams.");
+
+ if (bInput)
+ {
+ m_xInStream = xHelper.openFileRead(sFileName);
+ m_xSeek = UnoRuntime.queryInterface(
+ com.sun.star.io.XSeekable.class,
+ m_xInStream);
+ }
+ else
+ {
+ m_xOutStream = xHelper.openFileWrite(sFileName);
+ m_xSeek = UnoRuntime.queryInterface(
+ com.sun.star.io.XSeekable.class,
+ m_xOutStream);
+ }
+ }
+ catch(com.sun.star.uno.Exception exUno)
+ {
+ throw new com.sun.star.io.NotConnectedException(exUno);
+ }
+ }
+
+ /**
+ * following methods simulates the XInputStream.
+ * The notice all actions inside the internal protocol
+ * and try to map all necessary functions to the internal
+ * open in-stream.
+ */
+ public int readBytes( /*OUT*/ byte[][] lData ,
+ /*IN*/ int nBytesToRead ) throws com.sun.star.io.NotConnectedException ,
+ com.sun.star.io.BufferSizeExceededException,
+ com.sun.star.io.IOException
+ {
+ if (m_xInStream == null)
+ {
+ throw new com.sun.star.io.NotConnectedException("stream not open");
+ }
+
+ int nRead = 0;
+ try
+ {
+ nRead = m_xInStream.readBytes(lData,nBytesToRead);
+ }
+ catch (com.sun.star.io.NotConnectedException exConnect) {
+ }
+ catch (com.sun.star.io.BufferSizeExceededException exBuffer ) {
+ }
+ catch (com.sun.star.io.IOException exIO ) {
+ }
+ catch (com.sun.star.uno.RuntimeException exRuntime) {
+ }
+
+ return nRead;
+ }
+
+
+
+ public int readSomeBytes( /*OUT*/ byte[][] lData ,
+ /*IN*/ int nMaxBytesToRead ) throws com.sun.star.io.NotConnectedException ,
+ com.sun.star.io.BufferSizeExceededException ,
+ com.sun.star.io.IOException
+ {
+ if (m_xInStream == null)
+ {
+ throw new com.sun.star.io.NotConnectedException("stream not open");
+ }
+
+ int nRead = 0;
+ try
+ {
+ nRead = m_xInStream.readSomeBytes(lData,nMaxBytesToRead);
+ }
+ catch (com.sun.star.io.NotConnectedException exConnect) {
+ }
+ catch (com.sun.star.io.BufferSizeExceededException exBuffer ) {
+ }
+ catch (com.sun.star.io.IOException exIO ) {
+ }
+ catch (com.sun.star.uno.RuntimeException exRuntime) {
+ }
+
+ return nRead;
+ }
+
+
+
+ public void skipBytes( /*IN*/ int nBytesToSkip ) throws com.sun.star.io.NotConnectedException ,
+ com.sun.star.io.BufferSizeExceededException ,
+ com.sun.star.io.IOException
+ {
+ if (m_xInStream == null)
+ {
+ throw new com.sun.star.io.NotConnectedException("stream not open");
+ }
+
+ try
+ {
+ m_xInStream.skipBytes(nBytesToSkip);
+ }
+ catch (com.sun.star.io.NotConnectedException exConnect) {
+ }
+ catch (com.sun.star.io.BufferSizeExceededException exBuffer ) {
+ }
+ catch (com.sun.star.io.IOException exIO ) {
+ }
+ catch (com.sun.star.uno.RuntimeException exRuntime) {
+ }
+ }
+
+
+
+ public int available() throws com.sun.star.io.NotConnectedException,
+ com.sun.star.io.IOException
+ {
+ if (m_xInStream == null)
+ {
+ throw new com.sun.star.io.NotConnectedException("stream not open");
+ }
+
+ int nAvailable = 0;
+ try
+ {
+ nAvailable = m_xInStream.available();
+ }
+ catch (com.sun.star.io.NotConnectedException exConnect) {
+ }
+ catch (com.sun.star.io.IOException exIO ) {
+ }
+ catch (com.sun.star.uno.RuntimeException exRuntime) {
+ }
+
+ return nAvailable;
+ }
+
+
+
+ public void closeInput() throws com.sun.star.io.NotConnectedException,
+ com.sun.star.io.IOException
+ {
+ if (m_xInStream == null)
+ {
+ throw new com.sun.star.io.NotConnectedException("stream not open");
+ }
+
+ try
+ {
+ m_xInStream.closeInput();
+ }
+ catch (com.sun.star.io.NotConnectedException exConnect) {
+ }
+ catch (com.sun.star.io.IOException exIO ) {
+ }
+ catch (com.sun.star.uno.RuntimeException exRuntime) {
+ }
+ }
+
+
+ /**
+ * following methods simulates the XOutputStream.
+ * The notice all actions inside the internal protocol
+ * and try to map all necessary functions to the internal
+ * open out-stream.
+ */
+ public void writeBytes( /*IN*/byte[] lData ) throws com.sun.star.io.NotConnectedException ,
+ com.sun.star.io.BufferSizeExceededException ,
+ com.sun.star.io.IOException
+ {
+ if (m_xOutStream == null)
+ {
+ throw new com.sun.star.io.NotConnectedException("stream not open");
+ }
+
+ try
+ {
+ m_xOutStream.writeBytes(lData);
+ }
+ catch (com.sun.star.io.NotConnectedException exConnect) {
+ }
+ catch (com.sun.star.io.BufferSizeExceededException exBuffer ) {
+ }
+ catch (com.sun.star.io.IOException exIO ) {
+ }
+ catch (com.sun.star.uno.RuntimeException exRuntime) {
+ }
+ }
+
+
+
+ public void flush() throws com.sun.star.io.NotConnectedException ,
+ com.sun.star.io.BufferSizeExceededException ,
+ com.sun.star.io.IOException
+ {
+ if (m_xOutStream == null)
+ {
+ throw new com.sun.star.io.NotConnectedException("stream not open");
+ }
+
+ try
+ {
+ m_xOutStream.flush();
+ }
+ catch (com.sun.star.io.NotConnectedException exConnect) {
+ }
+ catch (com.sun.star.io.BufferSizeExceededException exBuffer ) {
+ }
+ catch (com.sun.star.io.IOException exIO ) {
+ }
+ catch (com.sun.star.uno.RuntimeException exRuntime) {
+ }
+ }
+
+
+
+ public void closeOutput() throws com.sun.star.io.NotConnectedException ,
+ com.sun.star.io.BufferSizeExceededException,
+ com.sun.star.io.IOException
+ {
+ if (m_xOutStream == null)
+ {
+ throw new com.sun.star.io.NotConnectedException("stream not open");
+ }
+
+ try
+ {
+ m_xOutStream.closeOutput();
+ }
+ catch (com.sun.star.io.NotConnectedException exConnect) {
+ }
+ catch (com.sun.star.io.BufferSizeExceededException exBuffer ) {
+ }
+ catch (com.sun.star.io.IOException exIO ) {
+ }
+ catch (com.sun.star.uno.RuntimeException exRuntime) {
+ }
+ }
+
+
+ /**
+ * following methods simulates the XSeekable.
+ * The notice all actions inside the internal protocol
+ * and try to map all necessary functions to the internal
+ * open stream.
+ */
+ public void seek( /*IN*/long nLocation ) throws com.sun.star.lang.IllegalArgumentException,
+ com.sun.star.io.IOException
+ {
+ if (m_xSeek == null)
+ {
+ throw new com.sun.star.io.IOException("stream not seekable");
+ }
+
+ try
+ {
+ m_xSeek.seek(nLocation);
+ }
+ catch (com.sun.star.lang.IllegalArgumentException exArg ) {
+ }
+ catch (com.sun.star.io.IOException exIO ) {
+ }
+ catch (com.sun.star.uno.RuntimeException exRuntime) {
+ }
+ }
+
+
+
+ public long getPosition() throws com.sun.star.io.IOException
+ {
+ if (m_xSeek == null)
+ {
+ throw new com.sun.star.io.IOException("stream not seekable");
+ }
+
+ long nPos = 0;
+ try
+ {
+ nPos = m_xSeek.getPosition();
+ }
+ catch (com.sun.star.io.IOException exIO ) {
+ }
+ catch (com.sun.star.uno.RuntimeException exRuntime) {
+ }
+
+ return nPos;
+ }
+
+
+
+ public long getLength() throws com.sun.star.io.IOException
+ {
+ if (m_xSeek == null)
+ {
+ throw new com.sun.star.io.IOException("stream not seekable");
+ }
+
+ long nLen = 0;
+ try
+ {
+ nLen = m_xSeek.getLength();
+ }
+ catch (com.sun.star.io.IOException exIO ) {
+ }
+ catch (com.sun.star.uno.RuntimeException exRuntime) {
+ }
+
+ return nLen;
+ }
+}
diff --git a/qadevOOo/runner/helper/StringHelper.java b/qadevOOo/runner/helper/StringHelper.java
new file mode 100644
index 000000000..7e265d62f
--- /dev/null
+++ b/qadevOOo/runner/helper/StringHelper.java
@@ -0,0 +1,64 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package helper;
+
+public class StringHelper
+{
+
+ public static String removeQuoteIfExists(String _sPath)
+ {
+ String sNewPath = _sPath;
+
+ if (_sPath.startsWith("\"") ||
+ _sPath.startsWith("'"))
+ {
+ // remove trailing quotes, if exists
+ sNewPath = sNewPath.substring(1);
+ }
+
+ if (_sPath.endsWith("\"") ||
+ _sPath.endsWith("'"))
+ {
+ // remove trailing quotes, if exists
+ sNewPath = sNewPath.substring(0, sNewPath.length() - 1);
+ }
+ return sNewPath;
+ }
+
+
+
+ /**
+ * Convert a value to a string with a given length, if the len is greater the len of the value string representation
+ * fill it's front with '0'
+ * So ("5", 4) will result in a string "0005"
+ */
+ public static String createValueString(int _nValue, int _nLen)
+ {
+ String sValue = String.valueOf(_nValue);
+ StringBuffer a = new StringBuffer();
+ while (_nLen > sValue.length())
+ {
+ a.append('0');
+ _nLen --;
+ }
+ a.append(sValue);
+ return a.toString();
+ }
+
+}
diff --git a/qadevOOo/runner/helper/URLHelper.java b/qadevOOo/runner/helper/URLHelper.java
new file mode 100644
index 000000000..395be4cd0
--- /dev/null
+++ b/qadevOOo/runner/helper/URLHelper.java
@@ -0,0 +1,151 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package helper;
+
+// __________ Imports __________
+
+// exceptions
+import java.io.File;
+import java.net.MalformedURLException;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+
+/**
+ * It collects some static helper functions to handle URLs.
+ * Sometimes it's necessary to convert URL from/to system paths.
+ * Or from string to strutural notations (e.g. com.sun.star.util.URL).
+ * And sometimes java had another notation then the office it has.
+ *
+ */
+public class URLHelper
+{
+
+
+ /**
+ * Because the office need URLs for loading/saving documents
+ * we must convert used system paths.
+ * And java use another notation for file URLs ... correct it.
+ *
+ * @param aSystemPath
+ * represent the file in system notation
+ *
+ * @return [String]
+ * a file url which represent the given system path
+ */
+ public static String getFileURLFromSystemPath( File aSystemPath )
+ {
+ String sFileURL = null;
+ try
+ {
+ sFileURL = aSystemPath.toURI().toURL().toString();
+ }
+ catch( MalformedURLException exWrong )
+ {
+ }
+
+ // problem of java: file URL's are coded with 1 slash instead of 2 or 3 ones!
+ // => correct this problem first, otherwise office can't use these URL's
+ if(
+ (sFileURL != null ) &&
+ sFileURL.startsWith("file:/") &&
+ !sFileURL.startsWith("file://")
+ )
+ {
+ StringBuffer sWorkBuffer = new StringBuffer(sFileURL);
+ sWorkBuffer.insert(6,"//");
+ sFileURL = sWorkBuffer.toString();
+ }
+
+ return sFileURL;
+ }
+
+
+
+ /**
+ * The same as getFileURLFromSystemPath() before but uses string parameter instead
+ * of a File type. It exists to suppress converting of necessary parameters in the
+ * outside code. But of course getFileURLFromSystemPath(File) will be a little bit faster
+ * then this method ...
+ *
+ * @param sSystemPath
+ * represent the file in system notation
+ *
+ * @return [String]
+ * a file url which represent the given system path
+ */
+ public static String getFileURLFromSystemPath( String sSystemPath )
+ {
+ return getFileURLFromSystemPath(new File(sSystemPath));
+ }
+
+
+
+ /**
+ * Return a name list of all available files of a directory.
+ * We filter pure sub directories names. All other files
+ * are returned as full qualified URL strings. So they can be
+ * used for further purposes. One parameter define the start directory,
+ * another one describe the url protocol, which the return URL names should have.
+ *
+ * @param sStartDir
+ * the start directory, which should include all test files
+ *
+ * @return [Vector]
+ * a filtered list of java File objects of all available files of the start dir
+ * and all accessible sub directories.
+ */
+ public static ArrayList<File> getSystemFilesFromDir(String sStartDir)
+ {
+ File aRoot = new File(sStartDir);
+
+ if (! aRoot.exists())
+ return null;
+
+ if (! aRoot.isDirectory())
+ return null;
+
+ File[] lAllFiles = aRoot.listFiles();
+ if (lAllFiles == null )
+ return null;
+
+ ArrayList<File> lFilteredFiles = new ArrayList<File>(lAllFiles.length);
+
+ for (int i=0; i<lAllFiles.length; ++i)
+ {
+ if (lAllFiles[i].isFile())
+ lFilteredFiles.add(lAllFiles[i]);
+ else
+ if (lAllFiles[i].isDirectory())
+ {
+ // recursion!
+ ArrayList<File> lSubFiles = URLHelper.getSystemFilesFromDir(lAllFiles[i].getPath());
+ if (lSubFiles != null)
+ {
+ Iterator<File> aSnapshot = lSubFiles.iterator();
+ while (aSnapshot.hasNext()) {
+ lFilteredFiles.add(aSnapshot.next());
+ }
+ }
+ }
+ }
+
+ return lFilteredFiles;
+ }
+}
diff --git a/qadevOOo/runner/helper/UnoProvider.java b/qadevOOo/runner/helper/UnoProvider.java
new file mode 100644
index 000000000..017c2227c
--- /dev/null
+++ b/qadevOOo/runner/helper/UnoProvider.java
@@ -0,0 +1,141 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package helper;
+
+import java.util.HashMap;
+
+import lib.TestParameters;
+import util.PropertyName;
+import util.utils;
+
+import com.sun.star.comp.helper.Bootstrap;
+import com.sun.star.lang.XMultiComponentFactory;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.XComponentContext;
+
+/**
+ * Bootstrap UNO from a Java environment.
+ * Needed parameters:
+ * <ol>
+ * <li>
+ * <ul>
+ * <li>UNORC - complete path to the unorc file</li>
+ * </ul>
+ * </li>
+ * <li>
+ * <ul>
+ * <li>AppExecutionCommand - path to the soffice executable</li>
+ * <li>OS - the operating system in case it's Windows, because the
+ * unorc is called uno.ini</li>
+ * </ul>
+ * </li>
+ * </ol>
+ */
+public class UnoProvider implements AppProvider {
+
+ /**
+ * Close existing office: calls disposeManager()
+ * @param param The test parameters.
+ * @param closeIfPossible Not needed, since UNO is bootstrapped by this
+ * class in every case.
+ * @return True, if bootstrapping worked.
+ */
+ public boolean closeExistingOffice(TestParameters param,
+ boolean closeIfPossible) {
+ return disposeManager(param);
+ }
+
+ /**
+ * Dispose the UNO environment: just clears the bootstrapped
+ * MultiServiceFactory
+ * @param param The test parameters.
+ * @return True, if bootstrapping worked.
+ */
+ public boolean disposeManager(TestParameters param) {
+ param.remove("ServiceManager");
+ System.gc();
+ util.utils.pause(1000);
+ return true;
+ }
+
+ /**
+ * Bootstrap UNO and return the created MultiServiceFactory.
+ * @param param The test parameters.
+ * @return A created MultiServiceFactory.
+ */
+ public Object getManager(TestParameters param) {
+ XMultiServiceFactory xMSF = param.getMSF();
+ if (xMSF == null) {
+ // bootstrap UNO.
+ String unorcName = getUnorcName(param);
+ HashMap<String,String> env = new HashMap<String,String>();
+ env.put("SYSBINDIR", getSysBinDir(param));
+
+ XComponentContext xContext = null;
+ try {
+ xContext = Bootstrap.defaultBootstrap_InitialComponentContext(
+ unorcName, env);
+ }
+ catch(Exception e) {
+ e.printStackTrace();
+ System.out.println("Could not get XComponentContext. Maybe you must add program folder to LD_LIBRARY_PATH");
+ return null;
+ }
+ XMultiComponentFactory xMCF = xContext.getServiceManager();
+ xMSF = UnoRuntime.queryInterface(
+ XMultiServiceFactory.class, xMCF);
+ }
+ return xMSF;
+ }
+
+ private String getUnorcName(TestParameters param) {
+ String unorcName = (String)param.get("UNORC");
+ if (unorcName == null) {
+ String office = (String)param.get("AppExecutionCommand");
+ // determine unorc name: unorc or uno.ini on windows
+ unorcName = (String)param.get(PropertyName.UNORC_NAME);
+ // use '/', because this will be a URL in any case.
+ unorcName = office.substring(0, office.indexOf("program")+7) +
+ "/" + unorcName;
+ }
+ unorcName = utils.getFullURL(unorcName);
+ if (param.getBool(PropertyName.DEBUG_IS_ACTIVE)) {
+ System.out.println("UnoUcr: " + unorcName);
+ }
+ return unorcName;
+ }
+
+ private String getSysBinDir(TestParameters param) {
+ String base = (String)param.get("AppExecutionCommand");
+ if (base == null)
+ base = (String)param.get("UNORC");
+
+ if (base == null)
+ return null;
+
+ String sysbindir = base.substring(0,
+ base.indexOf("program")+7);
+
+ sysbindir = utils.getFullURL(sysbindir);
+ if (param.getBool(PropertyName.DEBUG_IS_ACTIVE)) {
+ System.out.println("SysBinDir: " + sysbindir);
+ }
+ return sysbindir;
+ }
+}