diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /qadevOOo/runner | |
parent | Initial commit. (diff) | |
download | libreoffice-upstream/4%7.4.7.tar.xz libreoffice-upstream/4%7.4.7.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
93 files changed, 17742 insertions, 0 deletions
diff --git a/qadevOOo/runner/base/TestBase.java b/qadevOOo/runner/base/TestBase.java new file mode 100644 index 000000000..9fd0b2deb --- /dev/null +++ b/qadevOOo/runner/base/TestBase.java @@ -0,0 +1,30 @@ +/* + * 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 base; + +import lib.TestParameters; +/** + * + * Base Interface to execute a given TestJob + */ +public interface TestBase { + + boolean executeTest(TestParameters param) throws Exception; + +} diff --git a/qadevOOo/runner/base/java_complex.java b/qadevOOo/runner/base/java_complex.java new file mode 100644 index 000000000..e0f6b7967 --- /dev/null +++ b/qadevOOo/runner/base/java_complex.java @@ -0,0 +1,150 @@ +/* + * 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 base; + +import complexlib.ComplexTestCase; +import util.DynamicClassLoader; +import share.DescGetter; +import stats.OutProducerFactory; +import helper.ComplexDescGetter; +import helper.AppProvider; +import helper.CfgParser; +import share.DescEntry; +import share.LogWriter; +import stats.Summarizer; +import lib.TestParameters; +import util.PropertyName; +import java.io.UnsupportedEncodingException; + +/** + * Test base for executing a java complex test. + * @see base.TestBase + */ +public class java_complex implements TestBase +{ + + /** + * This function executes the complex tests given as parameter "-o" or "TestJob". It queries for the correspond class + * and creates the JobDescription. + * @return true of all tests run successfully, else false + */ + public boolean executeTest(TestParameters param) + { + // get the test job + String testJob = ((String) param.get("TestJob")); + + DescGetter descGetter = new ComplexDescGetter(); + // get the test jobs + DescEntry[] entries = descGetter.getDescriptionFor(testJob, null, true); + + if (entries == null) { + System.out.println("Couldn't get Description for Job: " + testJob); + + return false; + } + + return executeTest(param, entries); + } + + /** + * This function run the given DescEntry[] as ComplexTest + * @return true of all tests run successfully, else false + */ + public boolean executeTest(TestParameters param, DescEntry[] entries) + { + DynamicClassLoader dcl = new DynamicClassLoader(); + ComplexTestCase testClass = null; + boolean returnVal = true; + +// the concept of the TimeOut depends on runner logs. If the runner log, +// for example to start a test method, the timeout was reset. This is not +// while the test itself log something like "open document...". +// A property of complex test could be that it has only one test method +// which works for several minutes. In this case the TimeOut get not trigger +// and the office was killed. +// In complex tests just use "ThreadTimeOut" as timeout. + + for (int i = 0; i < entries.length; i++) + { + + if (entries[i] == null) + { + continue; + } + String iniName = entries[i].longName; + iniName = iniName.replace('.', '/'); + CfgParser ini = new CfgParser(iniName + ".props"); + ini.getIniParameters(param); + + LogWriter log = (LogWriter) dcl.getInstance((String) param.get("LogWriter")); + + AppProvider office = null; + if (!param.getBool("NoOffice")) + { + try + { + office = (AppProvider) dcl.getInstance("helper.OfficeProvider"); + Object msf = office.getManager(param); + if (msf == null) + { + returnVal = false; + continue; + } + param.put("ServiceFactory", msf); + } + catch (IllegalArgumentException e) + { + office = null; + } + catch (UnsupportedEncodingException e) + { + office = null; + } + } + log.initialize(entries[i], param.getBool(PropertyName.LOGGING_IS_ACTIVE)); + entries[i].Logger = log; + + // create an instance + try + { + testClass = (ComplexTestCase) dcl.getInstance(entries[i].longName); + } + catch (java.lang.Exception e) + { + e.printStackTrace(); + return false; + } + testClass.executeMethods(entries[i], param); + + Summarizer sum = new Summarizer(); + sum.summarizeUp(entries[i]); + + if (office != null) + { + office.closeExistingOffice(param, false); + } + + LogWriter out = OutProducerFactory.createOutProducer(param); + + out.initialize(entries[i], true); + out.summary(entries[i]); + returnVal &= entries[i].State.endsWith("OK"); + } + return returnVal; + } +} diff --git a/qadevOOo/runner/base/java_fat.java b/qadevOOo/runner/base/java_fat.java new file mode 100644 index 000000000..bd21b0861 --- /dev/null +++ b/qadevOOo/runner/base/java_fat.java @@ -0,0 +1,472 @@ +/* + * 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 base; + +import helper.APIDescGetter; +import helper.AppProvider; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import lib.MultiMethodTest; +import lib.TestCase; +import lib.TestEnvironment; +import lib.TestParameters; +import lib.TestResult; +import share.DescEntry; +import share.DescGetter; +import share.LogWriter; +import stats.OutProducerFactory; +import stats.Summarizer; +import util.DynamicClassLoader; + +import com.sun.star.lang.XMultiServiceFactory; + +/** + * + * this class handles tests written in java and running on a fat Office + */ +public class java_fat implements TestBase { + + private boolean logging = true; + private DynamicClassLoader m_aDynamicClassLoader = null; + + private lib.TestParameters m_aParams; + private AppProvider m_aOffice; + + public boolean executeTest(lib.TestParameters _aParams) throws Exception { + m_aParams = _aParams; + + m_aDynamicClassLoader = new DynamicClassLoader(); + + DescGetter dg = new APIDescGetter(); + String job = (String) m_aParams.get("TestJob"); + String ExclusionFile = (String) m_aParams.get("ExclusionList"); + ArrayList<String> exclusions = null; + boolean retValue = true; + boolean isDebug = m_aParams.getBool("DebugIsActive"); + logging = m_aParams.getBool("LoggingIsActive"); + boolean keepdocument = m_aParams.getBool("KeepDocument"); + boolean newOffice = m_aParams + .getBool(util.PropertyName.NEW_OFFICE_INSTANCE); + if (keepdocument) { + System.setProperty("KeepDocument", "true"); + } + if (ExclusionFile != null) { + exclusions = getExclusionList(ExclusionFile, isDebug); + } + + String sDescriptionPath = (String) m_aParams.get("DescriptionPath"); + DescEntry[] entries = dg.getDescriptionFor(job, sDescriptionPath, + isDebug); + + if (entries == null) { + System.out.println("Couldn't get Description for Job: " + job); + + return false; + } + + m_aOffice = startOffice(m_aParams); + + boolean firstRun = true; + + // Run through all entries (e.g. sw.SwXBookmark.*) + + for (int l = 0; l < entries.length; l++) { + DescEntry entry = entries[l]; + + if (entry == null) { + continue; + } + + if (entry.hasErrorMsg) { + System.out.println(entries[l].ErrorMsg); + retValue = false; + continue; + } + + if (!firstRun && newOffice) { + if (!m_aOffice.closeExistingOffice(m_aParams, true)) { + m_aOffice.disposeManager(m_aParams); + } + startOffice(m_aParams); + } + firstRun = false; + + XMultiServiceFactory msf = m_aParams.getMSF(); + + if (msf == null) { + retValue = false; + continue; + } + + // get some helper classes + Summarizer sumIt = new Summarizer(); + TestCase tCase = getTestCase(entry); + if (tCase == null) { + continue; + } + + util.utils.pause(2000); + + System.out.println("Creating: " + entry.entryName); + + LogWriter log = (LogWriter) m_aDynamicClassLoader + .getInstance((String) m_aParams.get("LogWriter")); + log.initialize(entry, logging); + entry.UserDefinedParams = m_aParams; + + tCase.setLogWriter((PrintWriter) log); + tCase.initializeTestCase(m_aParams); + + TestEnvironment tEnv = getTestEnvironment(tCase, entry); + if (tEnv == null) { + continue; + } + + for (int j = 0; j < entry.SubEntryCount; j++) { + DescEntry aSubEntry = entry.SubEntries[j]; + final boolean bIsToTest = aSubEntry.isToTest; + if (!bIsToTest) { + Summarizer.summarizeDown(aSubEntry, "not part of the job"); + continue; + } + + final String sLongEntryName = aSubEntry.longName; + + if ((exclusions != null) + && (exclusions.contains(sLongEntryName))) { + Summarizer.summarizeDown(aSubEntry, "known issue"); + continue; + } + + // this will shown in test itself + + LogWriter ifclog = (LogWriter) m_aDynamicClassLoader + .getInstance((String) m_aParams.get("LogWriter")); + + ifclog.initialize(aSubEntry, logging); + aSubEntry.UserDefinedParams = m_aParams; + aSubEntry.Logger = ifclog; + + if (tEnv.isDisposed()) { + closeExistingOffice(); + tEnv = getEnv(entry, m_aParams); + tCase = tEnv.getTestCase(); + } + + lib.TestResult res = null; + + // run the interface test twice if it failed. + int countInterfaceTestRun = 0; + boolean finished = false; + while (!finished) { + try { + countInterfaceTestRun++; + finished = true; + res = executeInterfaceTest(aSubEntry, tEnv, m_aParams); + } catch (IllegalArgumentException iae) { + System.out.println("Couldn't load class " + + aSubEntry.entryName + ":"); + iae.printStackTrace(System.out); + Summarizer.summarizeDown(aSubEntry, iae.getMessage()); + } catch (java.lang.NoClassDefFoundError iae) { + System.out.println("Couldn't load class " + + aSubEntry.entryName + ":"); + iae.printStackTrace(System.out); + Summarizer.summarizeDown(aSubEntry, iae.getMessage()); + } catch (java.lang.RuntimeException e) { + closeExistingOffice(); + tEnv = getEnv(entry, m_aParams); + tCase = tEnv.getTestCase(); + if (countInterfaceTestRun < 2) { + finished = false; + } else { + Summarizer.summarizeDown(aSubEntry, e.toString() + + ".FAILED"); + } + } + } + setState(aSubEntry, res); + + sumIt.summarizeUp(aSubEntry); + + LogWriter sumIfc = OutProducerFactory + .createOutProducer(m_aParams); + aSubEntry.UserDefinedParams = m_aParams; + sumIfc.initialize(aSubEntry, logging); + sumIfc.summary(aSubEntry); + } + + try { + if (!keepdocument) { + tCase.cleanupTestCase(m_aParams); + } + } catch (Exception e) { + System.err.println("couldn't cleanup:" + e.toString()); + } catch (java.lang.NoClassDefFoundError e) { + System.err.println("couldn't cleanup:" + e.toString()); + } + + sumIt.summarizeUp(entry); + + LogWriter sumObj = OutProducerFactory.createOutProducer(m_aParams); + + sumObj.initialize(entry, logging); + sumObj.summary(entry); + } + + if (entries.length > 0) { + System.out.println(); + + int counter = 0; + System.out + .println("Failures that appeared during scenario execution:"); + + for (int i = 0; i < entries.length; i++) { + final String sState = entries[i].State; + if (!sState.endsWith("OK")) { + System.out.println("\t " + entries[i].longName); + counter++; + } + } + + System.out.println(counter + " of " + entries.length + + " tests failed"); + if (counter != 0) { + retValue = false; + } + } + + closeExistingOffice(); + return retValue; + } + + private TestEnvironment getTestEnvironment(TestCase tCase, DescEntry entry) { + TestEnvironment tEnv = null; + + try { + tEnv = tCase.getTestEnvironment(m_aParams); + } catch (Exception e) { + System.out.println("Exception while creating " + + tCase.getObjectName()); + System.out.println("Message " + e.getMessage()); + e.printStackTrace(); + tEnv = null; + } catch (java.lang.UnsatisfiedLinkError e) { + System.out.println("Exception while creating " + + tCase.getObjectName()); + System.out.println("Message " + e.getMessage()); + tEnv = null; + } catch (java.lang.NoClassDefFoundError e) { + System.out.println("Exception while creating " + + tCase.getObjectName()); + System.out.println("Message " + e.getMessage()); + tEnv = null; + } + + if (tEnv == null) { + Summarizer.summarizeDown(entry, + "Couldn't create " + tCase.getObjectName()); + + LogWriter sumObj = OutProducerFactory.createOutProducer(m_aParams); + entry.UserDefinedParams = m_aParams; + sumObj.initialize(entry, logging); + sumObj.summary(entry); + } + return tEnv; + } + + private TestCase getTestCase(DescEntry _aEntry) { + TestCase tCase = null; + + try { + tCase = (TestCase) m_aDynamicClassLoader.getInstance("mod._" + + _aEntry.entryName); + } catch (java.lang.IllegalArgumentException ie) { + _aEntry.ErrorMsg = ie.getMessage(); + _aEntry.hasErrorMsg = true; + } catch (java.lang.NoClassDefFoundError ie) { + _aEntry.ErrorMsg = ie.getMessage(); + _aEntry.hasErrorMsg = true; + } + + if (tCase == null) { + Summarizer.summarizeDown(_aEntry, _aEntry.ErrorMsg); + + LogWriter sumObj = OutProducerFactory.createOutProducer(m_aParams); + _aEntry.UserDefinedParams = m_aParams; + sumObj.initialize(_aEntry, logging); + sumObj.summary(_aEntry); + } + return tCase; + } + + private void setState(DescEntry aSubEntry, lib.TestResult res) { + if (res != null) { + for (int k = 0; k < aSubEntry.SubEntryCount; k++) { + DescEntry aSubSubEntry = aSubEntry.SubEntries[k]; + if (res.hasMethod(aSubSubEntry.entryName)) { + aSubSubEntry.State = res.getStatusFor( + aSubSubEntry.entryName).toString(); + } + } + } + } + + private TestEnvironment getEnv(DescEntry entry, TestParameters param) throws Exception { + TestCase tCase = null; + + try { + tCase = (TestCase) m_aDynamicClassLoader.getInstance("mod._" + + entry.entryName); + } catch (java.lang.IllegalArgumentException ie) { + entry.ErrorMsg = ie.getMessage(); + entry.hasErrorMsg = true; + } catch (java.lang.NoClassDefFoundError ie) { + entry.ErrorMsg = ie.getMessage(); + entry.hasErrorMsg = true; + } + + System.out.println("Creating: " + entry.entryName); + + entry.UserDefinedParams = param; + + LogWriter log = (LogWriter) m_aDynamicClassLoader + .getInstance((String) param.get("LogWriter")); + log.initialize(entry, logging); + tCase.setLogWriter((PrintWriter) log); + + try { + tCase.initializeTestCase(param); + TestEnvironment tEnv = tCase.getTestEnvironment(param); + if (tEnv == null) { + throw new Exception("Could not get env for '" + entry.entryName + "'"); + } + return tEnv; + } catch (com.sun.star.lang.DisposedException de) { + System.out.println("Office disposed"); + closeExistingOffice(); + throw de; + } catch (Exception e) { + System.out.println(e.getMessage()); + + closeExistingOffice(); + + entry.ErrorMsg = e.getMessage(); + entry.hasErrorMsg = true; + throw e; + } + } + + private void closeExistingOffice() { + helper.ProcessHandler ph = (helper.ProcessHandler) m_aParams + .get("AppProvider"); + + if (ph != null) { + m_aOffice.closeExistingOffice(m_aParams, true); + util.utils.pause(5000); + } + + } + + private ArrayList<String> getExclusionList(String url, boolean debug) { + ArrayList<String> entryList = new ArrayList<String>(); + String line = "#"; + BufferedReader exclusion = null; + + try { + InputStreamReader reader = new InputStreamReader(new FileInputStream(url), "UTF-8"); + exclusion = new BufferedReader(reader); + } catch (java.io.UnsupportedEncodingException uee) { + if (debug) { + System.out.println("Couldn't decode file " + url); + } + + return entryList; + } catch (java.io.FileNotFoundException fnfe) { + if (debug) { + System.out.println("Couldn't find file " + url); + } + + return entryList; + } + + try { + while (line != null) { + try { + if (!line.startsWith("#") && (line.length() > 1)) { + entryList.add(line.trim()); + } + + line = exclusion.readLine(); + } catch (java.io.IOException ioe) { + if (debug) { + System.out + .println("Exception while reading exclusion list"); + } + + return entryList; + } + } + } finally { + try { + exclusion.close(); + } catch (java.io.IOException ioe) { + } + } + + return entryList; + } + + private TestResult executeInterfaceTest(DescEntry entry, + TestEnvironment tEnv, TestParameters param) + throws IllegalArgumentException, java.lang.NoClassDefFoundError { + MultiMethodTest ifc = (MultiMethodTest) m_aDynamicClassLoader + .getInstance(entry.entryName); + return ifc.run(entry, tEnv, param); + } + + private AppProvider startOffice(lib.TestParameters param) throws UnsupportedEncodingException { + if (m_aDynamicClassLoader == null) { + m_aDynamicClassLoader = new DynamicClassLoader(); + } + + String officeProviderName = (String) param.get("OfficeProvider"); + AppProvider office = (AppProvider) m_aDynamicClassLoader + .getInstance(officeProviderName); + + if (office == null) { + System.out.println("ERROR: Wrong parameter 'OfficeProvider', " + + " it cannot be instantiated."); + System.exit(-1); + } + + XMultiServiceFactory msf = (XMultiServiceFactory) office + .getManager(param); + + if (msf != null) { + param.put("ServiceFactory", msf); + } + + return office; + } +} diff --git a/qadevOOo/runner/base/java_fat_service.java b/qadevOOo/runner/base/java_fat_service.java new file mode 100644 index 000000000..5a1a72bab --- /dev/null +++ b/qadevOOo/runner/base/java_fat_service.java @@ -0,0 +1,237 @@ +/* + * 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 base; + + +import java.io.PrintWriter; + +import lib.TestParameters; +import lib.TestCase; +import lib.MultiMethodTest; +import lib.TestEnvironment; +import util.DynamicClassLoader; + +import share.DescEntry; +import share.DescGetter; +import helper.APIDescGetter; + +import share.LogWriter; +import stats.Summarizer; + +/** + * this class handles tests written in java and running on a fat Office + * with the runner as a service. + */ +public class java_fat_service implements TestBase { + + protected boolean debug = false; + protected LogWriter log = null; + + public boolean executeTest(lib.TestParameters param) { + DynamicClassLoader dcl = new DynamicClassLoader(); + log = (LogWriter)dcl.getInstance((String)param.get("LogWriter")); + debug = ((Boolean) param.get("DebugIsActive")).booleanValue(); + + DescGetter dg = new APIDescGetter(); + String job = (String) param.get("TestJob"); + boolean retValue = true; + + //get Job-Descriptions + log.println("Getting Descriptions for Job: "+job); + DescEntry[] entries = dg.getDescriptionFor(job, + (String) param.get("DescriptionPath"),debug); + + if (entries == null ) { + log.println("Couldn't get Description for Job"); + return false; + } + + for (int l=0;l<entries.length;l++) { + + if (entries[l] == null ) { + continue; + } + + if (entries[l].hasErrorMsg) { + log.println(entries[l].ErrorMsg); + continue; + } + + DescEntry entry = entries[l]; + + //get some helper classes + Summarizer sumIt = new Summarizer(); + + TestCase tCase = null; + try { + tCase = (TestCase) + dcl.getInstance("mod._"+entry.entryName); + } catch (java.lang.IllegalArgumentException ie) { + entry.ErrorMsg=ie.getMessage(); + entry.hasErrorMsg=true; + } + + if (tCase == null) { + Summarizer.summarizeDown(entry,entry.ErrorMsg); + LogWriter sumObj = (LogWriter)dcl.getInstance( + (String)param.get("OutProducer")); + sumObj.initialize(entry,true); + entry.UserDefinedParams = param; + sumObj.summary(entry); + continue; + } + + log.println("Creating: "+tCase.getObjectName()); + + log.initialize(entry,true); + entry.UserDefinedParams = param; + TestEnvironment tEnv = null; + try { + tCase.setLogWriter((PrintWriter) log); + tCase.initializeTestCase(param); + tEnv = tCase.getTestEnvironment(param); + } catch (Exception e) { + log.println("Exception while creating "+tCase.getObjectName()); + log.println("Exception: " + e); + log.println("Message "+e.getMessage()); + tEnv = null; + } + if (tEnv == null) { + Summarizer.summarizeDown(entry,"Couldn't create "+tCase.getObjectName()); + LogWriter sumObj = (LogWriter)dcl.getInstance( + (String)param.get("OutProducer")); + sumObj.initialize(entry,true); + entry.UserDefinedParams = param; + sumObj.summary(entry); + continue; + } + log.println("Created "+tCase.getObjectName()+"\n"); + + for (int j=0;j<entry.SubEntryCount;j++) { + if (!entry.SubEntries[j].isToTest) { + Summarizer.summarizeDown(entry.SubEntries[j],"not part of the job"); + continue; + } + + log.println("running: "+entry.SubEntries[j].entryName); + + LogWriter ifclog = (LogWriter)dcl.getInstance( + (String)param.get("LogWriter")); + + ifclog.initialize(entry.SubEntries[j],true); + entry.SubEntries[j].UserDefinedParams = param; + entry.SubEntries[j].Logger = ifclog; + + if (tEnv == null || tEnv.isDisposed()) { + tEnv = getEnv(entry,param); + } + + MultiMethodTest ifc = null; + lib.TestResult res = null; + try { + ifc = (MultiMethodTest) dcl.getInstance( + entry.SubEntries[j].entryName); + res = ifc.run(entry.SubEntries[j],tEnv,param); + } catch (IllegalArgumentException iae) { + log.println("Couldn't load class "+entry.SubEntries[j].entryName); + log.println("**** "+iae.getMessage()+" ****"); + Summarizer.summarizeDown(entry.SubEntries[j],iae.getMessage()); + } catch (java.lang.RuntimeException e) { + tEnv = getEnv(entry,param); + ifc = (MultiMethodTest) dcl.getInstance( + entry.SubEntries[j].entryName); + if ((tEnv != null) && (ifc != null)) { + res = ifc.run(entry.SubEntries[j],tEnv,param); + } + else + { + res = null; + } + } + if (res != null) { + for (int k=0;k<entry.SubEntries[j].SubEntryCount;k++) { + if (res.hasMethod(entry.SubEntries[j].SubEntries[k].entryName)) { + entry.SubEntries[j].SubEntries[k].State= + res.getStatusFor(entry.SubEntries[j].SubEntries[k].entryName).toString(); + } + } + } + sumIt.summarizeUp(entry.SubEntries[j]); + + LogWriter sumIfc = (LogWriter)dcl.getInstance( + (String)param.get("OutProducer")); + + sumIfc.initialize(entry.SubEntries[j],true); + entry.SubEntries[j].UserDefinedParams = param; + sumIfc.summary(entry.SubEntries[j]); + } + try { + tCase.cleanupTestCase(param); + } catch (Exception e) { + e.printStackTrace((PrintWriter)log); + } + sumIt.summarizeUp(entry); + LogWriter sumObj = (LogWriter)dcl.getInstance( + (String)param.get("OutProducer")); + sumObj.initialize(entry,true); + sumObj.summary(entry); + } + if (entries.length > 1) { + log.println(""); + int counter = 0; + log.println("Failures that appeared during scenario execution:"); + for (int i=0;i<entries.length;i++) { + if (! entries[i].State.endsWith("OK")) { + log.println("\t "+entries[i].longName); + counter++; + } + } + log.println(counter +" of "+entries.length + " tests failed" ); + } + + return retValue; + } + + protected TestEnvironment getEnv(DescEntry entry, TestParameters param) { + DynamicClassLoader dcl = new DynamicClassLoader(); + log = (LogWriter)dcl.getInstance((String)param.get("LogWriter")); + + TestEnvironment tEnv = null; + + try { + TestCase tCase = (TestCase) dcl.getInstance("mod._"+entry.entryName); + log.println("Creating: " + tCase.getObjectName()); + log.initialize(entry, true); + entry.UserDefinedParams = param; + tCase.setLogWriter((PrintWriter) log); + try { + tCase.initializeTestCase(param); + tEnv = tCase.getTestEnvironment(param); + } catch (com.sun.star.lang.DisposedException de) { + log.println("Office disposed"); + } + } catch (java.lang.Exception ie) { + entry.ErrorMsg=ie.getMessage(); + entry.hasErrorMsg=true; + } + + return tEnv; + } + +} diff --git a/qadevOOo/runner/complexlib/Assurance.java b/qadevOOo/runner/complexlib/Assurance.java new file mode 100644 index 000000000..4fbf3755d --- /dev/null +++ b/qadevOOo/runner/complexlib/Assurance.java @@ -0,0 +1,146 @@ +/* + * 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 complexlib; + +/** + * I have removed the assure(...) functions from ComplexTestCase due to the fact now I can + * use the functions every where and don't need to be a ComplexTestCase any longer. + */ +public class Assurance +{ + /** Used to indicate that we should continue with test method, even if check fails */ + public enum ContinueWithTest { + YES, NO + } + + /** State of the current test method **/ + protected boolean bSuccessful = true; + + /** The message if the test did fail **/ + protected String message = null; + + + /** + * Assure that s is true. + * This function generates "Assure failed." as standard message. + * @param s The condition that should be true. + */ + protected void assure(boolean s) { + assure("Assure failed.", s, ContinueWithTest.NO); + } + + /** + * Assure that s is true. + * The given message will be only evaluated, if s is false. + * @param msg The message that is evaluated. + * @param s The condition that should be true. + */ + protected void assure(String msg, boolean s) { + assure(msg, s, ContinueWithTest.NO); + } + + /** + * Assure that two int values are equal + * @param message the message to print when the equality test fails + * @param expected specifies the expected int value + * @param actual specifies the actual int value + */ + protected void assureEquals( String message, int expected, int actual ) { + assureEquals( message, Integer.valueOf( expected ), Integer.valueOf( actual ), ContinueWithTest.NO ); + } + + /** + * Assure that two string values are equal + * @param message the message to print when the equality test fails + * @param expected specifies the expected string value + * @param actual specifies the actual string value + */ + protected void assureEquals( String message, String expected, String actual ) { + assureEquals( message, expected, actual, ContinueWithTest.NO ); + } + + /** + * assures the two given sequences are of equal length, and have equal content + */ + public <T> void assureEquals( String i_message, T[] i_expected, T[] i_actual, ContinueWithTest i_continue ) + { + if ( i_expected.length != i_actual.length ) + failed( i_message + ": expected element count: " + i_expected.length + ", actual element count: " + i_actual.length ); + for ( int i=0; i<i_expected.length; ++i ) + { + assureEquals( i_message + ": mismatch at element pos " + i, i_expected[i], i_actual[i], i_continue ); + } + } + + /** + * Mark the currently executed method as failed. + * with the given message. + * @param msg The message of the failure. + */ + protected void failed(String msg) { + assure(msg, false, ContinueWithTest.NO); + } + + /** + * Assure that s is true. + * The given message will be only evaluated, if s is false. + * Normally, assure() leaves the current test method, and the next one + * is executed. With the parameter 'cont' set to true, the current test + * method will continue.<br> + * The current method will of course marked as failed. + * @param msg The message that is evaluated. + * @param s The condition that should be true. + * @param cont if YES, continue with test method, even if s is false. + */ + protected void assure(String msg, boolean s, ContinueWithTest cont) { + bSuccessful &= s; + if (!s) { + message += msg + "\r\n"; + if (cont == ContinueWithTest.NO) { + throw new AssureException(msg); + } + } + } + + private void assureEquals( String message, Object expected, Object actual, ContinueWithTest cont ) { + assure( message + " (expected: " + expected.toString() + ", actual: " + actual.toString() + ")", + expected.equals( actual ), cont ); + } + + /** + * Mark the currently executed method as failed. + * with the given message. + * The given message will be only evaluated, if s is false. + * With the parameter 'cont' set to true, the current test + * method will continue.<br> + * The current method will of course marked as failed. + * @param msg The message that is evaluated. + * @param cont if YES, continue with test method, even if s is false. + */ + protected void failed(String msg, ContinueWithTest cont) { + assure(msg, false, cont); + } + + public static class AssureException extends RuntimeException { + + private AssureException(String msg) { + super(msg); + } + } +} diff --git a/qadevOOo/runner/complexlib/ComplexTestCase.java b/qadevOOo/runner/complexlib/ComplexTestCase.java new file mode 100644 index 000000000..ab95d1eed --- /dev/null +++ b/qadevOOo/runner/complexlib/ComplexTestCase.java @@ -0,0 +1,296 @@ +/* + * 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 complexlib; + +import java.lang.reflect.Method; +import share.DescEntry; +import lib.TestParameters; +import lib.StatusException; +import share.LogWriter; +import share.ComplexTest; +import java.io.PrintWriter; + +/** + * Base class for all complex tests. + */ +public abstract class ComplexTestCase extends Assurance implements ComplexTest +{ + + /** The test parameters **/ + protected TestParameters param = null; + /** Log writer **/ + protected LogWriter log = null; + /** + * The method name which will be written into f.e. the data base + **/ + private String mTestMethodName = null; + + private boolean m_bBeforeCalled; + + /** + * is called before the real test starts + */ + private void before() + { + try + { + Method before = this.getClass().getMethod("before", new Class[] {} ); + before.invoke(this, new Object[] {} ); + + m_bBeforeCalled = true; + } + catch (java.lang.NoSuchMethodException e) + { + m_bBeforeCalled = true; + } + catch (java.lang.IllegalAccessException e) + { + log.println("Cannot access the 'before()' method, although it" + " is there. Is this ok?"); + } + catch (java.lang.reflect.InvocationTargetException e) + { + Throwable t = e.getTargetException(); + if (!(t instanceof RuntimeException) || bSuccessful) + { + log.println(t.toString()); + if (message == null) + { + message = "Exception in before() method.\n\r" + t.getMessage(); + } + bSuccessful = false; + t.printStackTrace((PrintWriter) log); + } + } + + } + + /** Description entry **/ + + private void test_method(DescEntry _entry) + { + + /* Maximal time one method is allowed to execute + * Can be set with parameter 'ThreadTimeOut' + **/ + int nThreadTimeOut = param.getInt("ThreadTimeOut"); + if (nThreadTimeOut == 0) + { + nThreadTimeOut = 300000; + } + + for (int i = 0; i < _entry.SubEntries.length; i++) + { + + DescEntry subEntry = _entry.SubEntries[i]; + if (m_bBeforeCalled) + { + bSuccessful = true; + message = ""; + } + else + { + // set all test methods on failed, if 'before()' did not work. + subEntry.State = message; + subEntry.hasErrorMsg = true; + subEntry.ErrorMsg = message; + continue; + } + Method testMethod = null; + try + { + String entryName = subEntry.entryName; + Object[] parameter = null; + + int posLeftParenthesis = entryName.indexOf('('); + if (posLeftParenthesis != -1) + { + String sParameter = entryName.substring(posLeftParenthesis + 1, entryName.indexOf(')')); + mTestMethodName = entryName; + parameter = new String[] { sParameter }; + entryName = entryName.substring(0, posLeftParenthesis); + testMethod = this.getClass().getMethod(entryName, new Class[] { String.class }); + } + else + { + testMethod = this.getClass().getMethod(entryName, new Class[] {} ); + mTestMethodName = entryName; + } + + MethodThread th = new MethodThread(testMethod, this, parameter, (java.io.PrintWriter) log); + log.println("Starting " + mTestMethodName); + th.start(); + + try + { + // some tests are very dynamic in their execution time so that + // a threadTimeOut fails. In this cases the logging mechanism + // is a useful way to detect that an office respective a test + // is running and not death. + // But way ThreadTimeOut? + // There exists a complex test which uses no office. Therefore + // a logging mechanism to detect a stalled test. + int lastPing = -1; + int newPing = 0; + + int sleepingStep = 1000; + int factor = 0; + + while (th.isAlive() && (lastPing != newPing || factor * sleepingStep < nThreadTimeOut)) + { + Thread.sleep(sleepingStep); + factor++; + // if a test starts the office itself it the watcher is a + // new one. + share.Watcher ow = (share.Watcher) param.get("Watcher"); + if (ow != null) + { + lastPing = newPing; + newPing = ow.getPing(); + factor = 0; + } + } + } + catch (InterruptedException e) + { + } + if (th.isAlive()) + { + log.println("Destroy " + mTestMethodName); + th.stopRunning(); + subEntry.State = "Test did sleep for " + (nThreadTimeOut / 1000) + " seconds and has been killed!"; + subEntry.hasErrorMsg = true; + subEntry.ErrorMsg = subEntry.State; + continue; + } + else + { + log.println("Finished " + mTestMethodName); + if (th.hasErrorMessage()) + { + subEntry.State = th.getErrorMessage(); + subEntry.hasErrorMsg = true; + subEntry.ErrorMsg = subEntry.State; + continue; + } + } + } + catch (java.lang.Exception e) + { + log.println(e.getClass().getName()); + String msg = e.getMessage(); + log.println("Message: " + msg); + e.printStackTrace((PrintWriter) log); + subEntry.State = "SKIPPED.FAILED"; + subEntry.hasErrorMsg = true; + subEntry.ErrorMsg = (msg == null ? "" : msg); + continue; + } + subEntry.State = (bSuccessful ? "COMPLETED.OK" : message); + subEntry.hasErrorMsg = !bSuccessful; + subEntry.ErrorMsg = message; + } + } + + /** + * after() is called after the test is done + */ + private void after() + { + if (m_bBeforeCalled) + { + // the after() method + try + { + Method after = this.getClass().getMethod("after", new Class[] {}); + after.invoke(this, new Object[] {} ); + } + catch (java.lang.NoSuchMethodException e) + { + // simply ignore + } + catch (java.lang.IllegalAccessException e) + { + // simply ignore + } + catch (java.lang.reflect.InvocationTargetException e) + { + Throwable t = e.getTargetException(); + if (!(t instanceof StatusException)) + { + log.println(t.toString()); + if (message == null) + { + message = "Exception in after() method.\n\r" + t.getMessage(); + } + else + { + message += "Exception in \'after()\' method.\n\r" + t.getMessage(); + } + log.println("Message: " + message); + t.printStackTrace((PrintWriter) log); + } + } + } + + } + + + + /** + * Call test. It is expected, that an environment is + * given to this test. + * + * @param entry The name of the test method that should be called. + * @param environment The environment for the test. + */ + public void executeMethods(DescEntry entry, TestParameters environment) + { + m_bBeforeCalled = false; + + // get the environment + param = environment; + log = entry.Logger; + + + // start with the before() method + before(); + + //executeMethodTests + test_method(entry); + + // cleanup + after(); + } + + + /** + * Implement this method in the Complex test. + * @return All test method names. + */ + public abstract String[] getTestMethodNames(); + + /** + * Return a name for the test or tested object. + * Override to give an own name. + * @return As default, the name of this class. + */ + public String getTestObjectName() + { + return this.getClass().getName(); + } +} diff --git a/qadevOOo/runner/complexlib/MethodThread.java b/qadevOOo/runner/complexlib/MethodThread.java new file mode 100644 index 000000000..28ea770eb --- /dev/null +++ b/qadevOOo/runner/complexlib/MethodThread.java @@ -0,0 +1,118 @@ +/* + * 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 complexlib; + +import java.io.PrintWriter; +import java.lang.reflect.Method; + +/** + * Invoke a method of a class in an own thread. Provide a method to end + * the thread. + */ +public class MethodThread extends Thread +{ + + /** The method that should be executed **/ + private final Method mTestMethod; + /** The object that implements the method **/ + private final Object mInvokeClass; + /** A PrintWriter for debug Output **/ + private final PrintWriter mLog; + /** An Error String **/ + private String mErrMessage = null; + /** Did an Exception happen? **/ + private boolean mExceptionHappened = false; + private Object[] mParameter = null; + + public MethodThread(Method testMethod, Object invokeClass, Object[] parameter, PrintWriter log) + { + mTestMethod = testMethod; + mInvokeClass = invokeClass; + mParameter = parameter; + mLog = log; + } + + /** + * Invoke the method. + */ + @Override + public void run() + { + try + { + mTestMethod.invoke(mInvokeClass, mParameter); + } + catch (IllegalAccessException e) + { + e.printStackTrace(mLog); + mErrMessage = e.getMessage(); + mExceptionHappened = true; + } + catch (java.lang.reflect.InvocationTargetException e) + { + Throwable t = e.getTargetException(); + if (!(t instanceof ComplexTestCase.AssureException)) + { + t.printStackTrace(mLog); + mErrMessage = t.getMessage(); + if (mErrMessage == null) + { + mErrMessage = t.toString(); + } + mExceptionHappened = true; + } + + } + } + + /** + * Get the error message + * @return The error message. + */ + public String getErrorMessage() + { + return mErrMessage; + } + + /** + * Is there an error message? + * @return True, if an error did happen. + */ + public boolean hasErrorMessage() + { + return mExceptionHappened; + } + + /** + * Stop the running method. + */ + public void stopRunning() + { + try + { + interrupt(); + } + catch (SecurityException e) + { + e.printStackTrace(mLog); + mErrMessage = e.getMessage(); + mExceptionHappened = true; + } + } +} diff --git a/qadevOOo/runner/complexlib/ShowTargets.java b/qadevOOo/runner/complexlib/ShowTargets.java new file mode 100644 index 000000000..f655e1330 --- /dev/null +++ b/qadevOOo/runner/complexlib/ShowTargets.java @@ -0,0 +1,102 @@ +/* + * 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 complexlib; + +import java.util.ArrayList; + +public class ShowTargets +{ + public static void main( String[] args ) + { + ArrayList<String> targets = new ArrayList<String>(); + ArrayList<String> descs = new ArrayList<String>(); + + targets.add( "run" ); + descs.add( "runs all complex tests in this module" ); + + int maxTargetLength = 3; + + for ( int i = 0; i < args.length; ++i ) + { + String completePotentialClassName = args[i].replace( '/', '.' ); + + // filter + if ( completePotentialClassName.endsWith( ".TestCase" ) ) + continue; + if ( completePotentialClassName.endsWith( ".TestSkeleton" ) ) + continue; + + // get the class + Class<?> potentialTestClass = null; + try { potentialTestClass = Class.forName( completePotentialClassName ); } + catch( java.lang.ClassNotFoundException e ) + { + continue; + } + + // see if it is derived from complexlib.ComplexTestCase + Class<?> superClass = potentialTestClass.getSuperclass(); + while ( superClass != null ) + { + if ( superClass.getName().equals( "complexlib.ComplexTestCase" ) ) + { + String bareClassName = completePotentialClassName.substring( completePotentialClassName.lastIndexOf( '.' ) + 1 ); + String target = "run_" + bareClassName; + targets.add( target ); + descs.add( getShortTestDescription( potentialTestClass ) ); + + if ( maxTargetLength < target.length() ) + maxTargetLength = target.length(); + break; + } + superClass = superClass.getSuperclass(); + } + } + + System.out.println( "possible targets:" ); + for ( int i=0; i<targets.size(); ++i ) + { + // target + String target = targets.get(i); + // 'tab' + System.out.print( " " + target ); + for ( int s = maxTargetLength - target.length(); s>0; --s ) + System.out.print( " " ); + // description + System.out.println( " (" + descs.get(i) + ")" ); + } + } + + private static String getShortTestDescription( Class<?> _testClass ) + { + java.lang.reflect.Method getShortDescriptionMethod = null; + try { getShortDescriptionMethod = _testClass.getMethod( "getShortTestDescription", new Class[]{} ); } + catch( Exception e ) { } + + if ( getShortDescriptionMethod != null ) + { + try + { + return (String)getShortDescriptionMethod.invoke( null, new Object[]{} ); + } + catch( Exception e ) { } + } + return "no description provided by the test"; + } +} diff --git a/qadevOOo/runner/convwatch/DB.java b/qadevOOo/runner/convwatch/DB.java new file mode 100644 index 000000000..a9b2f7076 --- /dev/null +++ b/qadevOOo/runner/convwatch/DB.java @@ -0,0 +1,174 @@ +/* + * 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 convwatch; + +import java.sql.Connection; +import java.util.StringTokenizer; +import helper.OSHelper; + +public class DB extends DBHelper +{ + private static DB m_aDB = null; + + // private ctor + private DB() + { + } + + private static synchronized DB getDB() + { + if (m_aDB == null) + { + m_aDB = new DB(); + } + return m_aDB; + } + + private String m_sSourceVersion; + private String m_sDestinationVersion; + private String m_sDocumentPool; + private String m_sDocID; + private String m_sDBDistinct; + + public static void init(String _sDBInfoString) + { + if (_sDBInfoString == null) return; + getDB().fillVariables(_sDBInfoString); + getDB().updatestate_status("source started"); + } + + private String getEnvironment() + { + if (OSHelper.isWindows()) + { + return "wntmsci"; + } + else if ( OSHelper.isSolarisIntel()) + { + return "unxsoli"; + } + else if ( OSHelper.isSolarisSparc()) + { + return "unxsols"; + } + else if ( OSHelper.isLinuxIntel()) + { + return "unxlngi"; + } + else + { + GlobalLogWriter.get().println("DB: Unknown environment."); + GlobalLogWriter.get().println("DB: os.name := " + System.getProperty("os.name").toLowerCase()); + GlobalLogWriter.get().println("DB: os.arch := " + System.getProperty("os.arch")); + return ""; + } + } + + // fill some db access important variables with values given out of a simple string + // DOC_COMPARATOR_DB_INFO_STRING=p:m220,c:m224,d:demo_lla,src:m220,dest:m224,doc:demo_lla,id:294,distinct:81 + + private void fillVariables(String _sInfo) + { + fillDBConnection(_sInfo); + getEnvironment(); + + StringTokenizer aTokenizer = new StringTokenizer(_sInfo,",",false); + while (aTokenizer.hasMoreTokens()) + { + String sPart = aTokenizer.nextToken(); + if (sPart.startsWith("p:")) + { + m_sSourceVersion = sPart.substring(2); + GlobalLogWriter.get().println("DB: source version: " + m_sSourceVersion); + } + else if (sPart.startsWith("src:")) + { + m_sSourceVersion = sPart.substring(4); + GlobalLogWriter.get().println("DB: source version: " + m_sSourceVersion); + } + else if (sPart.startsWith("c:")) + { + m_sDestinationVersion = sPart.substring(2); + GlobalLogWriter.get().println("DB: destination version: " + m_sDestinationVersion); + } + else if (sPart.startsWith("dest:")) + { + m_sDestinationVersion = sPart.substring(5); + GlobalLogWriter.get().println("DB: destination version: " + m_sDestinationVersion); + } + else if (sPart.startsWith("d:")) + { + m_sDocumentPool = sPart.substring(2); + GlobalLogWriter.get().println("DB: documentpool version: " + m_sDocumentPool); + } + else if (sPart.startsWith("doc:")) + { + m_sDocumentPool = sPart.substring(4); + GlobalLogWriter.get().println("DB: documentpool version: " + m_sDocumentPool); + } + else if (sPart.startsWith("id:")) + { + m_sDocID = sPart.substring(3); + GlobalLogWriter.get().println("DB: docid: " + m_sDocID); + } + else if (sPart.startsWith("distinct:")) + { + m_sDBDistinct = sPart.substring(9); + GlobalLogWriter.get().println("DB: distinct: " + m_sDBDistinct); + } + else + { + } + } + } + + private void updatestate_status(String _sStatus) + { + Connection aCon = new ShareConnection().getConnection(); + + String sSet = "state=" + Quote(_sStatus); + String sWhere = getWhereClause(); + if (sWhere.length() > 0) + { + SQLupdateValue( aCon, "status", sSet, sWhere ); + } + } + + + private String getWhereClause() + { + StringBuffer aWhereClause = new StringBuffer(); + boolean bAND = false; + if (m_sDocID != null) + { + aWhereClause.append( "docid" ). append(sEqual) . append(m_sDocID); + bAND = true; + } + if (bAND) + { + aWhereClause.append(sAND); + } + if (m_sDBDistinct != null) + { + aWhereClause.append( "dbdistinct2" ). append(sEqual) . append(Quote(m_sDBDistinct)); + } + return aWhereClause.toString(); + } + +} diff --git a/qadevOOo/runner/convwatch/DBHelper.java b/qadevOOo/runner/convwatch/DBHelper.java new file mode 100644 index 000000000..34e1e1cfd --- /dev/null +++ b/qadevOOo/runner/convwatch/DBHelper.java @@ -0,0 +1,190 @@ +/* + * 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 convwatch; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.Statement; +import java.sql.SQLException; + +import java.util.StringTokenizer; + +class ShareConnection +{ + private Connection m_aConnection = null; + + public Connection getConnection() + { + if (m_aConnection == null) + { + try + { + m_aConnection = DBHelper.getMySQLConnection(); + } + catch(java.sql.SQLException e) + { + GlobalLogWriter.get().println("DB: ERROR: can't connect to DB."); + m_aConnection = null; + } + } + return m_aConnection; + } +} + + class MySQLThread extends Thread + { + private final Connection m_aCon; + private final String m_sSQL; + public MySQLThread(Connection _aCon, String _sSQL) + { + m_aCon = _aCon; + m_sSQL = _sSQL; + } + + @Override + public void run() + { + Statement oStmt = null; + if (m_aCon == null) + { + GlobalLogWriter.get().println("DB: ERROR: in ExecSQL, connection not established."); + return; + } + + try + { + try + { + oStmt = m_aCon.createStatement(); + + GlobalLogWriter.get().println("DB: " + m_sSQL); + /* ResultSet oResult = */ + oStmt.executeUpdate(m_sSQL); + } + finally + { + if (oStmt != null) + oStmt.close(); + } + } + catch(Exception e) + { + GlobalLogWriter.get().println("DB: Couldn't execute sql string '" + m_sSQL + "'"); + GlobalLogWriter.get().println("DB: Reason: " + e.getMessage()); + } + } + } + +public class DBHelper +{ + public void SQLupdateValue(Connection _aCon, String _sTableName, String _sSet, String _sWhere) + { + if (_aCon == null) + { + GlobalLogWriter.get().println("DB: ERROR: in SQLinsertValues, connection not established."); + return; + } + + StringBuffer aUpdateStr = new StringBuffer(); + + aUpdateStr.append( "UPDATE " ).append( _sTableName ) + .append( " SET " ).append( _sSet ) + .append( " WHERE " ).append( _sWhere ); + ExecSQL( _aCon, aUpdateStr.toString() ); + } + + private static String m_sDBServerName; + private static String m_sDBName; + private static String m_sDBUser; + private static String m_sDBPasswd; + + protected synchronized void fillDBConnection(String _sInfo) + { + StringTokenizer aTokenizer = new StringTokenizer(_sInfo,",",false); + while (aTokenizer.hasMoreTokens()) + { + String sPart = aTokenizer.nextToken(); + if (sPart.startsWith("db:")) + { + m_sDBName = sPart.substring(3); + } + else if (sPart.startsWith("user:")) + { + m_sDBUser = sPart.substring(5); + } + else if (sPart.startsWith("passwd:")) + { + m_sDBPasswd = sPart.substring(7); + } + else if (sPart.startsWith("server:")) + { + m_sDBServerName = sPart.substring(7); + } + } + } + + /** + * This method establishes a Connection<br> + * with the database 'module_unit' on jakobus + */ + + public static Connection getMySQLConnection() throws SQLException + { + try + { + Class.forName("org.gjt.mm.mysql.Driver"); + String sConnection = "jdbc:mysql://" + m_sDBServerName + ":3306/" + m_sDBName; + // Connection mysql = DriverManager.getConnection( + // "jdbc:mysql://jakobus:3306/jobs_convwatch","admin","admin"); + Connection mysql = DriverManager.getConnection(sConnection, m_sDBUser, m_sDBPasswd); + return mysql; + } + catch (ClassNotFoundException e) + { + GlobalLogWriter.get().println("DB: Class not found exception caught: " + e.getMessage()); + GlobalLogWriter.get().println("DB: Maybe mysql.jar is not added to the classpath."); + } + return null; + } + + private synchronized void ExecSQL(Connection _aCon, String _sSQL) + { + MySQLThread aSQLThread = new MySQLThread(_aCon, _sSQL); + aSQLThread.start(); + } + + + + public String Quote(String _sToQuote) + { + char ts = '\''; + char ds = '"'; + int nQuote = _sToQuote.indexOf(ts); + if (nQuote >= 0) + { + return ds + _sToQuote + ds; + } + return ts + _sToQuote + ts; + } + + public static final String sEqual = "="; + public static final String sAND = " AND "; + +} + diff --git a/qadevOOo/runner/convwatch/GlobalLogWriter.java b/qadevOOo/runner/convwatch/GlobalLogWriter.java new file mode 100644 index 000000000..f77845e56 --- /dev/null +++ b/qadevOOo/runner/convwatch/GlobalLogWriter.java @@ -0,0 +1,38 @@ +/* + * 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 convwatch; + +import share.LogWriter; +import stats.SimpleLogWriter; + +public class GlobalLogWriter +{ + private static LogWriter m_aGlobalLogWriter = null; + public static synchronized LogWriter get() + { + if (m_aGlobalLogWriter == null) + { + SimpleLogWriter aLog = new SimpleLogWriter(); + m_aGlobalLogWriter = aLog; + } + return m_aGlobalLogWriter; + } + +} + diff --git a/qadevOOo/runner/graphical/FileHelper.java b/qadevOOo/runner/graphical/FileHelper.java new file mode 100644 index 000000000..05acb5e35 --- /dev/null +++ b/qadevOOo/runner/graphical/FileHelper.java @@ -0,0 +1,73 @@ +/* + * 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 graphical; + +import helper.OSHelper; + +public class FileHelper +{ + public static String getSystemPathFromFileURL( String _sFileURL ) + { + String sSystemFile = null; + + if(_sFileURL.startsWith("file:///")) + { + if (OSHelper.isWindows()) + { + sSystemFile = _sFileURL.substring(8); + } + else + { + sSystemFile = _sFileURL.substring(7); + } + } + else if (_sFileURL.startsWith("file://")) + { + sSystemFile = _sFileURL.substring(5); + } + String fs = System.getProperty("file.separator"); + if (! fs.equals("/")) + { + if (sSystemFile == null) + throw new IllegalStateException("sSystemFile is unexpected null"); + sSystemFile = sSystemFile.replace ('/', fs.toCharArray ()[0]); + } +// FEATURE FOR UNC NEED!!! + return sSystemFile; + } + + public static String appendPath(String _sPath, String _sRelativePathToAdd) + { + String sNewPath = _sPath; + String fs = System.getProperty("file.separator"); + if (_sPath.startsWith("file:")) + { + fs = "/"; // we use a file URL so only '/' is allowed. + } + if (! (sNewPath.endsWith("/") || sNewPath.endsWith("\\") ) ) + { + sNewPath += fs; + } + sNewPath += _sRelativePathToAdd; + return sNewPath; + } + + +} + 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..a93e725fd --- /dev/null +++ b/qadevOOo/runner/helper/CfgParser.java @@ -0,0 +1,128 @@ +/* + * 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.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); + try { + prop.load(propFile); + System.out.println("Parsing properties from " + name); + } finally { + 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(); + try { + prop.load(in); + } finally { + in.close(); + } + } + } + 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> + * <oor:component-data xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" oor:name="Views" oor:package="org.openoffice.Office"><p> + * <node oor:name="Windows"><P> + * <<node oor:name="SplitWindow0" oor:op="replace"><P> + * <prop oor:name="Visible" oor:type="xs:boolean"><P> + * <value>false</value><P> + * </prop><P> + * <prop oor:name="WindowState" oor:type="xs:string"><P> + * <value/><P> + * </prop><P> + * <node oor:name="UserData"><P> + * <prop oor:name="UserItem" oor:op="replace" + * oor:type="xs:string"><P> + * <value>V1,2,0</value><P> + * </prop><P> + * </node><P> + * </node><P> + * </node><P> + * <P> + * <CODE>Definition</CODE><P> + * <ul> + * <li><CODE><node oor:name="Windows"></CODE> + * represents a <CODE>Set</CODE> and is a <CODE>XNameContainer</CODE></LI> + * <li><CODE><node oor:name="SplitWindow0"></CODE> + * represents a <CODE>Group</CODE> and is a <CODE>XNameReplace</CODE></LI> + * <li><CODE><prop oor:name="Visible"></CODE> + * represents a pr<CODE></CODE>operty of the group</li> + * <li><CODE><node oor:name="UserData"></CODE> + * represents a <CODE>extensible group</CODE> and is a <CODE>XNameContainer</CODE></LI> + * <li><CODE><prop oor:name="UserItem"></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..48c0910f6 --- /dev/null +++ b/qadevOOo/runner/helper/OfficeProvider.java @@ -0,0 +1,755 @@ +/* + * 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 continue the tests. + // Example: the UNO-API-Tests in the projects will be executed by calling + // 'dmake'. + 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..26c1f7875 --- /dev/null +++ b/qadevOOo/runner/helper/ProcessHandler.java @@ -0,0 +1,330 @@ +/* + * 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 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 isStarted = false; + private PrintStream stdIn = null; + private Process m_aProcess = null; + private boolean debug = false; + private boolean bUseOutput = true; + + /** + * 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 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); + } + } +} 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; + } +} diff --git a/qadevOOo/runner/lib/DynamicClassLoader.java b/qadevOOo/runner/lib/DynamicClassLoader.java new file mode 100644 index 000000000..5622221fb --- /dev/null +++ b/qadevOOo/runner/lib/DynamicClassLoader.java @@ -0,0 +1,86 @@ +/* + * 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 lib ; + +import java.lang.reflect.Constructor; + +/** + * @deprecated: moved to util package. + */ +@Deprecated +public class DynamicClassLoader { + + /** + * This method returns a class created by its name + * created by call to <code>Class.forName()</code>.<p> + * This method must be overridden if another loading + * policy is required for Component and Interface + * testing classes. + */ + public static Class<?> forName(String className) + throws ClassNotFoundException { + + return Class.forName(className) ; + } + + public Object getInstance(String className) + throws IllegalArgumentException { + try { + Class<?> cls = DynamicClassLoader.forName(className); + return cls.newInstance(); + } catch ( ClassNotFoundException e ) { + throw new IllegalArgumentException("Couldn't find " + className + + " " + e); + } catch ( IllegalAccessException e ) { + throw new IllegalArgumentException("Couldn't access " + className + + " " + e); + } catch ( InstantiationException e ) { + throw new IllegalArgumentException("Couldn't instantiate " + + className + " " + e); + } + } + + public Object getInstance(String className, Object[] ctorArgs) + throws IllegalArgumentException { + try { + Class<?> cls = DynamicClassLoader.forName(className); + Class<?>[] ctorType = new Class[ctorArgs.length]; + for(int i=0; i<ctorType.length; i++) { + ctorType[i] = ctorArgs[i].getClass(); + } + Constructor<?> ctor = cls.getConstructor(ctorType); + return ctor.newInstance(ctorArgs); + } catch ( ClassNotFoundException e ) { + throw new IllegalArgumentException("Couldn't find " + className + + " " + e); + } catch ( IllegalAccessException e ) { + throw new IllegalArgumentException("Couldn't access " + className + + " " + e); + } catch ( NoSuchMethodException e ) { + throw new IllegalArgumentException("Couldn't find constructor for " + className + + " " + e); + } catch ( java.lang.reflect.InvocationTargetException e ) { + throw new IllegalArgumentException("Couldn't invoke " + + className + " " + e); + } catch ( InstantiationException e ) { + throw new IllegalArgumentException("Couldn't instantiate " + + className + " " + e); + } + } +} diff --git a/qadevOOo/runner/lib/ExceptionStatus.java b/qadevOOo/runner/lib/ExceptionStatus.java new file mode 100644 index 000000000..d08557341 --- /dev/null +++ b/qadevOOo/runner/lib/ExceptionStatus.java @@ -0,0 +1,39 @@ +/* + * 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 lib; + +/** + * The class implements Status behaviour for exception runstate Status objects. + */ +class ExceptionStatus extends Status { + + /** + * Creates an instance of Status object with EXCEPTION runstate. + * + * @param t the exception an activity terminated with. + */ + ExceptionStatus( Throwable t ) { + super(RunState.EXCEPTION, false/*bSuccessful*/); + String message = t.getMessage(); + if (message != null) + runStateString = message; + else + runStateString = t.toString(); + } +}
\ No newline at end of file diff --git a/qadevOOo/runner/lib/MultiMethodTest.java b/qadevOOo/runner/lib/MultiMethodTest.java new file mode 100644 index 000000000..81a87f3f4 --- /dev/null +++ b/qadevOOo/runner/lib/MultiMethodTest.java @@ -0,0 +1,468 @@ +/* + * 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 lib; + +import java.io.PrintWriter; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; + +import share.DescEntry; +import stats.Summarizer; + +import com.sun.star.uno.UnoRuntime; + +/** + * The class supports method based interface tests development. + * + * <p>There are some points that should be fulfilled in a subclass to work + * correctly in the multi-method framework: + * + * 1. each subclass should define a public field named oObj of type tested + * by the subclass, e.g. 'public XText oObj;'. That field will be initialized + * by the MultiMethodTest code with the instance of the interface to test. + * In a case of service testing the field type should be XPropertySet. + * + * 2. for the test of each method of the tested interface(or a property in the + * case of service testing) should be method with the following signature + * provided: 'public void _<method name>()', e.g. 'public void _getText()'. + * The methods will be called by MultiMethodText code using reflection API + * for each method in the interface description. + * + * 3. to set status for a call 'tRes.tested(String method, + * boolean result)' should be used. For example 'tRes.tested("getText()", + * true)'. Also 'tRes.assert(String assertion, boolean result)' call can + * be used. Note, that one can call the methods not necessarily from the + * test for the tested method, but from other method tests too (in the + * MultiMethodTest subclass). See also TestResult and MultiMethodTest.tRes + * documentation. + * + * 4. the before() and after() methods can be overridden to perform some + * actions, accordingly, before and after calling the test methods. + * + * 5. besides tRes, there are some fields initialized in the MultiMethodTest, + * that can be used for implementing tests: + * + * - tEnv contains the environment tested + * - tParam contains parameters of the test + * - log a writer to log information about the test + * + * @see TestResult + */ +@SuppressWarnings("unused") +public class MultiMethodTest +{ + + /** + * Contains the TestEnvironment being tested, to allow for tests to access + * it. + */ + protected TestEnvironment tEnv; + /** + * Contains the TestParameters for the tests, to allow for tests to access + * it. + */ + protected TestParameters tParam; + /** + * Contains the Description for the test + * it. + */ + protected DescEntry entry; + /** + * Contains a writer to log an information about the interface testing, to + * allows for tests to access it. + */ + protected PrintWriter log; + /** + * Contains the TestResult instance for the interface test to collect + * information about methods test. + */ + protected TestResult tRes; + /** + * Contains names of the methods have been already called + */ + private final ArrayList<String> methCalled = new ArrayList<String>(10); + + /** + * Disposes the current test environment, which was corrupted by the test. + * + * @see #disposeEnvironment(TestEnvironment) + */ + public void disposeEnvironment() + { + tEnv.dispose(); + TestCase tCase = tEnv.getTestCase(); + tCase.disposeTestEnvironment(tEnv, tParam); + } + + /** + * Runs the interface test: its method tests. First, it initializes some + * of MultiMethodTest fields, like tRes, log, tEnv, etc. Then, it queries + * the tested interface and initializes 'oObj' field (defined in a + * subclass). Before calling method tests, before() method is called to allow + * initialization of s stuff before testing. Then, the method tests are + * called. After them, after() method is called, to allow cleaning up the + * stuff initialized in before() and test methods. + * + * @param entry the interface test state + * @param tEnv the environment to test + * @param tParam the parameters of the test + * + * @see #before + * @see #after + */ + public TestResult run(DescEntry entry, TestEnvironment tEnv, TestParameters tParam) + { + + log = (PrintWriter) entry.Logger; + + this.tEnv = tEnv; + this.tParam = tParam; + // this.log = log; + this.entry = entry; + this.tRes = new TestResult(); + Class<?> testedClass; + + System.out.print("checking: [" + entry.longName + "]"); + + // defining a name of the class corresponding to the tested interface + // or service + String testedClassName; + + testedClassName = getTestedClassName(); + + if (entry.EntryType.equals("service")) + { + testedClassName = "com.sun.star.beans.XPropertySet"; + } + + try + { + testedClass = Class.forName(testedClassName); + } + catch (ClassNotFoundException cnfE) + { + System.out.println(); + cnfE.printStackTrace(log); + log.println("could not find a class : " + getTestedClassName()); + return null; + } + System.out.println(" is iface: [" + testedClassName + "] testcode: [" + entry.entryName + "]"); + + Object oObj = UnoRuntime.queryInterface(testedClass, tEnv.getTestObject()); + + if (oObj == null) + { + if (entry.isOptional) + { + Summarizer.summarizeDown(entry, "Not supported but optional.OK"); + } + else + { + Summarizer.summarizeDown(entry, "queryInterface returned null.FAILED"); + entry.ErrorMsg = "queryInterface returned null"; + entry.hasErrorMsg = true; + } + + return null; + } + + //setting the field oObj + try + { + setField("oObj", oObj); + } + catch (Exception e) + { + e.printStackTrace(); + setSubStates(e.toString()); + return tRes; + } + + // to perform some stuff before all method tests + try + { + before(); + } + catch (Exception e) + { + e.printStackTrace(); + setSubStates(e.toString()); + return tRes; + } + + // executing methods tests + for (int i = 0; i < entry.SubEntryCount; i++) + { + DescEntry aSubEntry = entry.SubEntries[i]; + try + { + final String sEntryName = aSubEntry.entryName; + executeMethod(sEntryName); + } + catch (Exception e) + { + log.println("Exception while checking: " + aSubEntry.entryName + " : " + e.getMessage()); + } + } + + // to perform some stuff after all method tests + try + { + after(); + } + catch (Exception e) + { + } + + return tRes; + } + + /** + * Is called before calling method tests, but after initialization. + * Subclasses may override to perform actions before method tests. + */ + protected void before() throws Exception + { + } + + /** + * Is called after calling method tests. Subclasses may override + * to perform actions after method tests. + */ + protected void after() + { + } + + /** + * @return the name of the interface or the service tested. + */ + protected String getTestedClassName() + { + String clsName = this.getClass().getName(); + + int firstDot = clsName.indexOf('.'); + int lastDot = clsName.lastIndexOf('.'); + + String append = "com.sun.star."; + + if (entry.longName.indexOf("::drafts::com::") > -1) + { + append = "drafts.com.sun.star."; + } + + return append + clsName.substring(firstDot + 1, lastDot + 1) + clsName.substring(lastDot + 2); + } + + /** + * Sets a method status. + * + * @param methName the method name to set status + * @param methStatus the status to set to the method + */ + private void setStatus(String methName, Status methStatus) + { + tRes.tested(methName, methStatus); + } + + /** + * sets the substates + */ + private void setSubStates(String msg) + { + for (int k = 0; k < entry.SubEntryCount; k++) + { + entry.SubEntries[k].hasErrorMsg = true; + entry.SubEntries[k].ErrorMsg = msg; + if (entry.SubEntries[k].State.equals("UNKNOWN")) + { + entry.SubEntries[k].State = msg; + } + } + + } + + /** + * Checks if the <code>method</code> is optional in the service. + */ + protected boolean isOptional(String _method) + { + for (int k = 0; k < entry.SubEntryCount; k++) + { + final String sName = entry.SubEntries[k].entryName; + if (sName.equals(_method)) + { + final boolean bIsOptional = entry.SubEntries[k].isOptional; + return bIsOptional; + } + } + return false; + } + + /** + * Checks if the <code>method</code> test has been already called. + */ + private boolean isCalled(String method) + { + return methCalled.contains(method); + } + + /** + * Calling of the method indicates that the <code>method</code> test should + * be called. The method checks this and if it is not called, calls it. + * If the method is failed or skipped, it throws StatusException. + */ + protected void requiredMethod(String method) + { + log.println("starting required method: " + method); + executeMethod(method); + Status mtStatus = tRes.getStatusFor(method); + + if (mtStatus != null && (!mtStatus.isCompleted() || mtStatus.isFailed())) + { + log.println("! Required method " + method + " failed"); + throw new StatusException(mtStatus); + } + } + + /** + * Checks if the <code>method</code> was called, and if not, call it. + * On contrary to requiredMethod(), he method doesn't check its status. + */ + protected void executeMethod(String method) + { + if (!isCalled(method)) + { + log.println("Execute: " + method); + callMethod(method); + log.println(method + ": " + tRes.getStatusFor(method)); + log.println(); + } + } + + /** + * Just calls the <code>method</code> test. + */ + private void callMethod(String method) + { + methCalled.add(method); + invokeTestMethod(getMethodFor(method), method); + } + + /** + * Invokes a test method of the subclass using reflection API. Handles + * the method results and sets its status. + * + * @param meth the subclass' method to invoke + * @param methName the name of the method + */ + protected void invokeTestMethod(Method meth, String methName) + { + if (meth == null) + { + setStatus(methName, Status.skipped(false)); + } + else + { + Status stat; + + try + { + meth.invoke(this, new Object[0]); + return; + } + catch (InvocationTargetException itE) + { + Throwable t = itE.getTargetException(); + + if (t instanceof StatusException) + { + stat = ((StatusException) t).getStatus(); + } + else + { + t.printStackTrace(log); + stat = Status.exception(t); + } + } + catch (IllegalAccessException iaE) + { + iaE.printStackTrace(log); + stat = Status.exception(iaE); + } + catch (IllegalArgumentException iaE) + { + iaE.printStackTrace(log); + stat = Status.exception(iaE); + } + catch (ClassCastException ccE) + { + ccE.printStackTrace(log); + stat = Status.exception(ccE); + } + + setStatus(methName, stat); + } + } + + /** + * Finds a testing method for the <code>method</code> of the interface. + * + * @return the testing method, if found, <tt>null</tt> otherwise + */ + private Method getMethodFor(String method) + { + String mName = "_" + method; + + if (mName.endsWith("()")) + { + mName = mName.substring(0, mName.length() - 2); + } + + final Class<?>[] paramTypes = new Class[0]; + + try + { + return this.getClass().getDeclaredMethod(mName, paramTypes); + } + catch (NoSuchMethodException nsmE) + { + return null; + } + } + + /** + * @return the name of the interface tested + */ + public String getInterfaceName() + { + String clName = this.getClass().getName(); + return clName.substring(clName.lastIndexOf('.') + 1); + } + + private void setField(String fieldName, Object value) + throws NoSuchFieldException, IllegalAccessException + { + this.getClass().getField(fieldName).set(this, value); + } + + protected final void waitForEventIdle() { + util.utils.waitForEventIdle(tParam.getMSF()); + } + +} diff --git a/qadevOOo/runner/lib/MultiPropertyTest.java b/qadevOOo/runner/lib/MultiPropertyTest.java new file mode 100644 index 000000000..54e7122c4 --- /dev/null +++ b/qadevOOo/runner/lib/MultiPropertyTest.java @@ -0,0 +1,533 @@ +/* + * 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 lib; + +import com.sun.star.beans.Property; +import com.sun.star.beans.PropertyAttribute; +import com.sun.star.beans.PropertyVetoException; +import com.sun.star.beans.XPropertySet; +import com.sun.star.beans.XPropertySetInfo; +import com.sun.star.beans.UnknownPropertyException; +import com.sun.star.lang.IllegalArgumentException; +import com.sun.star.lang.WrappedTargetException; +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import util.ValueChanger; +import util.ValueComparer; +import util.utils; + +/** + * MultiPropertyTest extends the functionality of MultiMethodTest to support + * services testing. Since, in most cases, service tests has one method testing + * most of its properties, the MultiPropertyTest provides unified version of + * the method: testProperty(). + * + * <p>The testProperty() is called, when the MultiMethodTest's testing method + * is not found in the subclass. So, by defining such methods for properties + * the standard testing behaviour can be changed. + * + * <p>The testing behaviour also can be changed by overriding compare(), + * getNewVAlue() or toString(Object) methods, or by extending PropertyTester + * class. + * + * @see MultiMethodTest + * @see #testProperty(String) + * @see #testProperty(String, PropertyTester) + * @see #compare + * @see #toString(Object) + */ +public class MultiPropertyTest extends MultiMethodTest +{ + + /** + * Contains a XPropertySet interface of the tested object. Is initialized + * in MultiMethodTest code. + */ + public XPropertySet oObj; + + /** + * Overrides MultiMethodTest.invokeTestMethod(). If the test for the + * <code>meth</code> is not available (<code>meth</code> == <tt>null</tt>) + * calls testProperty method for the method. Otherwise calls + * super.invokeTestMethod(). + * + * @see MultiMethodTest#invokeTestMethod + */ + @Override + protected void invokeTestMethod(Method meth, String methName) + { + if (meth != null) + { + super.invokeTestMethod(meth, methName); + } + else + { + testProperty(methName); + } + } + + /** + * PropertyTester class defines how to test a property and defined + * to allow subclasses of MultiPropertyTest to change the testing + * behaviour more flexible, since the behaviour can be customized for + * each property separately, by providing subclass of PropertyTester + * and passing it to testProperty(String, PropertyTester method). + */ + public class PropertyTester + { + + /** + * The method defines the whole process of testing propName + * property. + * + * <p>First, it checks if the property exists(it maybe optional). + * Then, a value to set the property with is calculated with + * getNewValue method. Normally, the new value is calculated + * based on old value, but subclasses can override the behaviour + * (for example, if old value is null) and specify their own value. + * Then the property is set with that new value and the result( + * it maybe an exception too, for example a PropertyVetoException) + * is checked with checkResult method. + * + * @param propName - the property to test. + * @result - adds the result of testing propName property to + * MultiMethodTest.tRes. + */ + protected void testProperty(String propName) + { + XPropertySetInfo info = oObj.getPropertySetInfo(); + + if (info != null) + { + final boolean bHasProperty = info.hasPropertyByName(propName); + if (!bHasProperty) + { + if (isOptional(propName) || entry.isOptional) + { + // skipping optional property test + log.println("Property '" + propName + "' is optional and not supported"); + tRes.tested(propName, true); + return; + } + else + { + // cannot test the property + log.println("Tested XPropertySet does not contain'" + propName + "' property"); + tRes.tested(propName, false); + return; + } + } + } + + try + { + Object oldValue = oObj.getPropertyValue(propName); + + if( (oldValue==null) || utils.isVoid(oldValue) ) + { + // #i111560# method getNewValue() does not work with an empty oldValue + Property prop = info.getPropertyByName(propName); + if( (prop.Attributes & PropertyAttribute.MAYBEVOID) != 0 ) + { + // todo: implement a new test independent from method getNewValue() + log.println("changing initially empty MAYBEVOID properties is not supported by the test framework so far - skip test of property: " + propName); + tRes.tested(propName, true); + return; + } + else + { + log.println( "property '"+propName+"' is not set but is not MAYBEVOID"); + tRes.tested(propName, false); + return; + } + } + + Object newValue; + + // trying to create new value + try + { + newValue = getNewValue(propName, oldValue); + } + catch (java.lang.IllegalArgumentException e) + { + // skipping test since new value is not available + log.println("Cannot create new value for '" + propName + " : " + e.getMessage()); + return; + } + + // for an exception thrown during setting new value + // to pass it to checkResult method + Exception exception = null; + + try + { + log.println("try to set:"); + log.println("old = " + toString(oldValue)); + log.println("new = " + toString(newValue)); + oObj.setPropertyValue(propName, newValue); + } + catch (IllegalArgumentException e) + { + exception = e; + } + catch (PropertyVetoException e) + { + exception = e; + } + catch (WrappedTargetException e) + { + exception = e; + } + catch (UnknownPropertyException e) + { + exception = e; + } + catch (RuntimeException e) + { + exception = e; + } + + // getting result value + Object resValue = oObj.getPropertyValue(propName); + + // checking results + checkResult(propName, oldValue, newValue, resValue, exception); + } + catch (Exception e) + { + log.println("Exception occurred while testing property '" + propName + "'"); + e.printStackTrace(log); + tRes.tested(propName, false); + } + } + + /** + * The method checks result of setting a new value to the + * property based o the following arguments: + * @param propName - the property to test + * @param oldValue - the old value of the property, before changing it. + * @param newValue - the new value the property has been set with + * @param resValue - the value of the property after having changed it + * @param exception - if not null - the exception thrown by + * XPropertySet.setPropertyValue, else indicates + * normal method completion. + * + * <p>If the property is READ_ONLY, then either PropertyVetoException + * should be thrown or the value of property should not have changed + * (resValue is compared with oldValue with compare method). + * + * <p>If the property is not READ_ONLY, checks that the new value has + * been successfully set(resValue is compared with newValue with + * compare method). + * + * <p>If the exception is not null then(except the case of read-only + * property and PropertyVetoException above) it is rethrown to allow + * further catching it if needed. + * + * <p>Subclasses can override to change this behaviour. + */ + protected void checkResult(String propName, Object oldValue, + Object newValue, Object resValue, Exception exception) + throws Exception + { + XPropertySetInfo info = oObj.getPropertySetInfo(); + if (info == null) + { + log.println("Can't get XPropertySetInfo for property " + propName); + tRes.tested(propName, false); + return; + } + Property prop = info.getPropertyByName(propName); + + boolean readOnly = (prop.Attributes & PropertyAttribute.READONLY) != 0; + boolean maybeVoid = (prop.Attributes & PropertyAttribute.MAYBEVOID) != 0; + //check get-set methods + if (maybeVoid) + { + log.println("Property " + propName + " is void"); + } + if (readOnly) + { + log.println("Property " + propName + " is readOnly"); + } + if (util.utils.isVoid(oldValue) && !maybeVoid) + { + log.println(propName + " is void, but it's not MAYBEVOID"); + tRes.tested(propName, false); + } + else if (oldValue == null) + { + log.println(propName + " has null value, and therefore can't be changed"); + tRes.tested(propName, true); + } + else if (readOnly) + { + // check if exception was thrown + if (exception != null) + { + if (exception instanceof PropertyVetoException) + { + // the change of read only prohibited - OK + log.println("Property is ReadOnly and wasn't changed"); + log.println("Property '" + propName + "' OK"); + tRes.tested(propName, true); + } + else if (exception instanceof IllegalArgumentException) + { + // the change of read only prohibited - OK + log.println("Property is ReadOnly and wasn't changed"); + log.println("Property '" + propName + "' OK"); + tRes.tested(propName, true); + } + else if (exception instanceof UnknownPropertyException) + { + // the change of read only prohibited - OK + log.println("Property is ReadOnly and wasn't changed"); + log.println("Property '" + propName + "' OK"); + tRes.tested(propName, true); + } + else if (exception instanceof RuntimeException) + { + // the change of read only prohibited - OK + log.println("Property is ReadOnly and wasn't changed"); + log.println("Property '" + propName + "' OK"); + tRes.tested(propName, true); + } + else + { + throw exception; + } + } + else + { + // if no exception - check that value + // has not changed + if (!compare(resValue, oldValue)) + { + log.println("Read only property '" + propName + "' has changed"); + log.println("result = " + toString(resValue)); + tRes.tested(propName, false); + } + else + { + log.println("Read only property '" + propName + "' hasn't changed"); + log.println("Property '" + propName + "' OK"); + tRes.tested(propName, true); + } + } + } + else + { + if (exception == null) + { + // if no exception thrown + // check that the new value is set + if (!compare(resValue, newValue)) + { + log.println("Value for '" + propName + "' hasn't changed as expected"); + log.println("result = " + toString(resValue)); + if (!compare(resValue, oldValue)) + { + log.println("But it has changed."); + tRes.tested(propName, true); + } + else + { + tRes.tested(propName, false); + } + } + else + { + log.println("Property '" + propName + "' OK"); + log.println("result = " + toString(resValue)); + tRes.tested(propName, true); + } + } + else + { + throw exception; + } + } + } + + /** + * The method produces new value of the property from the oldValue. + * It returns the result of ValueChanger.changePValue method. + * Subclasses can override the method to return their own value, + * when the changePValue behavior is not enough, for example, + * when oldValue is null. + */ + protected Object getNewValue(String propName, Object oldValue) + throws java.lang.IllegalArgumentException + { + return ValueChanger.changePValue(oldValue, propName); + } + + /** + * The method compares obj1 and obj2. It calls + * MultiPropertyTest.compare, but subclasses can override to change + * the behavior, since normally compare calls Object.equals method + * which is not appropriate in some cases(e.g., structs with equals + * not overridden). + */ + protected boolean compare(Object obj1, Object obj2) + { + return MultiPropertyTest.this.compare(obj1, obj2); + } + + /** + * The method returns a String representation of the obj. It calls + * MultipropertyTest.toString(Object), but subclasses can override + * to change the behavior. + */ + protected String toString(Object obj) + { + return MultiPropertyTest.this.toString(obj); + } + } + + /** + * Extension for <code>PropertyTester</code> which switches two + * different values. <code>getNewValue()</code> method of this + * class returns one of these two values depending on the + * old value, so new value is not equal to old value. + */ + public class PropertyValueSwitcher extends PropertyTester + { + + Object val1 = null; + Object val2 = null; + + /** + * Constructs a property tester with two different values + * specified as parameters. + * + * @param val1 Not <code>null</code> value for the property + * tested. + * @param val2 Not <code>null</code> value for the property + * tested which differs from the first value. + */ + public PropertyValueSwitcher(Object val1, Object val2) + { + this.val1 = val1; + this.val2 = val2; + } + + /** + * Overridden method of <code>PropertyTester</code> which + * returns new value from two values specified. + * + * @return The second value if old value is equal to the first + * one, the first value otherwise. + */ + @Override + protected Object getNewValue(String propName, Object old) + { + if (ValueComparer.equalValue(val1, old)) + { + return val2; + } + else + { + return val1; + } + } + } + + /** + * The method performs testing of propName property using propTester. + */ + protected void testProperty(String propName, PropertyTester propTester) + { + propTester.testProperty(propName); + } + + /** + * The method performs testing of propName property. It uses PropertyTester + * instance for testing. + */ + protected void testProperty(String propName) + { + testProperty(propName, new PropertyTester()); + } + + /** + * Tests the property using <code>PropertyValueSwitcher</code> + * tester and two values for this property. + * + * @see PropertyValueSwitcher + */ + protected void testProperty(String propName, Object val1, Object val2) + { + testProperty(propName, new PropertyValueSwitcher(val1, val2)); + } + + /** + * Compares two object. In the implementation calls obj1.equals(obj2). + */ + protected boolean compare(Object obj1, Object obj2) + { + return ValueComparer.equalValue(obj1, obj2); + } + + /** + * Gets string representation of the obj. In the implementation + * returns obj.toString(). + */ + protected String toString(Object obj) + { + if (obj == null) { + return "null"; + } + StringBuilder s = new StringBuilder(obj.toString()); + if (obj.getClass().isArray()) { + int n = Array.getLength(obj); + s.append('[').append(n).append("]{"); + for (int i = 0; i != n; ++i) { + if (i != 0) { + s.append(", "); + } + s.append(toString(Array.get(obj, i))); + } + s.append('}'); + } else if (ValueChanger.isStructure(obj)) { + s.append('{'); + Field[] fields = obj.getClass().getFields(); + boolean first = true; + for (int i = 0; i != fields.length; ++i) { + if ((fields[i].getModifiers() & Modifier.STATIC) == 0) { + if (!first) { + s.append(", "); + } + first = false; + try { + s.append(toString(fields[i].get(obj))); + } catch (IllegalAccessException e) { + throw new RuntimeException("unexpected " + e, e); + } + } + } + s.append('}'); + } + return s.toString(); + } +} diff --git a/qadevOOo/runner/lib/RunState.java b/qadevOOo/runner/lib/RunState.java new file mode 100644 index 000000000..4b1eaa511 --- /dev/null +++ b/qadevOOo/runner/lib/RunState.java @@ -0,0 +1,43 @@ +/* + * 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 lib; + +public enum RunState { + + /** + * The constant represents COMPLETED runtime state. + */ + COMPLETED, + + /** + * The constant represents EXCEPTION runtime state. + */ + EXCEPTION, + + /** + * The constant represents SKIPPED runtime state. + */ + SKIPPED, + + /** + * This is a private indicator for a user defined runtime state + */ + USER_DEFINED + +} diff --git a/qadevOOo/runner/lib/SimpleStatus.java b/qadevOOo/runner/lib/SimpleStatus.java new file mode 100644 index 000000000..177bfb3f7 --- /dev/null +++ b/qadevOOo/runner/lib/SimpleStatus.java @@ -0,0 +1,97 @@ +/* + * 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 lib; + +/** + * The class is a simple implementation of Status class. It implements simple + * Status behaviour: its state, reason and log are defined when creating + * the SimpleSTatus instance. + */ +class SimpleStatus { + + /** + * The field is holding state of the status. + */ + private final boolean bSuccessful; + + /** + * The field is holding reason of the status. + */ + private final RunState runState; + + /** + * This is the run state: either SKIPPED, COMPLETED, etc. + * or user defined. Deriving classes can overwrite it for own run states. + */ + protected String runStateString; + + /** + * The constructor initialize state and reason field. + */ + protected SimpleStatus( RunState runState, boolean bSuccessful ) { + this.bSuccessful = bSuccessful; + this.runState = runState; + if ( runState == RunState.COMPLETED ) { + runStateString = "COMPLETED"; + } else if ( runState == RunState.SKIPPED ) { + runStateString = "SKIPPED"; + } else if ( runState == RunState.EXCEPTION ) { + runStateString = "EXCEPTION"; + } else { + runStateString = "UNKNOWN"; + } + } + + /** + * The constructor initialize state and reason field. + */ + protected SimpleStatus(String runStateString, boolean bSuccessful) { + this.bSuccessful = bSuccessful; + this.runState = RunState.USER_DEFINED; + this.runStateString = runStateString; + } + + public boolean isSuccessful() { + return bSuccessful; + } + + /** + * getRunState() implementation. Just returns th runState field value. + */ + public RunState getRunState() { + return runState; + } + + /** + * getReason implementation. Just returns the reason field value. + */ + public String getRunStateString() { + return runStateString; + } + + /** + * Get the result: passed or failed. + */ + public String getStateString() { + if (bSuccessful) + return "OK"; + return "FAILED"; + + } +} diff --git a/qadevOOo/runner/lib/Status.java b/qadevOOo/runner/lib/Status.java new file mode 100644 index 000000000..ae7f97ecf --- /dev/null +++ b/qadevOOo/runner/lib/Status.java @@ -0,0 +1,128 @@ +/* + * 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 lib; + +/** + * Status represents a result of a testing activity performed. The result is + * described in two ways: state and runtime state. The state describes if the + * activity was successful (OK state) or not (FAILED state). The runtime state + * describes what happened during the activity: the test can be: + * - COMPLETED - the activity completed normally (although it can complete with + * FAILED state) + * - SKIPPED - the activity was not performed because of a reason (it also can + * has OK or FAILED state) + * - EXCEPTION - the activity was abnormally terminated because of an + * unexpected exception. It always has a FAILED state. + * - EXCLUDED - the activity is expected to fail. The state represents how + * the state really completed: OK or FAILED. + * - other variants are not formalized now and can be represented by + * Status.failed() method. They always have a FAILED state. + */ +public class Status extends SimpleStatus { + + /** + * Construct a status: use runState and state + * @param runState either COMPLETED, SKIPPED, etc. + * @param bSuccessful OK or FAILED. + */ + public Status(RunState runState, boolean bSuccessful ) { + super(runState, bSuccessful); + } + + /** + * Construct a status: use own message and state. + * @param message An own message for the status. + * @param bSuccessful OK or FAILED. + */ + public Status(String message, boolean state) { + super( message, state ); + } + + /** + * This is a factory method for creating a Status representing normal + * activity termination. + * + * @param bSuccessful describes a test state (OK if state == true, FAILED + * otherwise). + */ + public static Status passed( boolean bSuccessful ) { + return new Status(RunState.COMPLETED, bSuccessful ); + } + + /** + * This is a factory method for creating a Status representing an exception + * activity termination. The Status always has FAILED state. + * + * @param t the exception with that the activity completed. + */ + public static Status exception( Throwable t ) { + return new ExceptionStatus( t ); + } + + /** + * This is a factory method for creating a Status representing a skipped + * activity. + * + * @param state describes a test state (OK if state == true, FAILED + * otherwise). + */ + public static Status skipped( boolean bSuccessful ) { + return new Status( RunState.SKIPPED, bSuccessful ); + } + + + + /** + * Creates a Status representing an activity failed for an arbitrary reason. + * It always has FAILED state. + * + * @param reason describes why the activity failed + */ + public static Status failed(final String reason) { + return new Status(reason, false/*bSuccessful*/); + } + + /** + * The method returns a human-readable description of the status. + * The Status implementation of the method returns the status state + * description and appends to it the reason, for example: + * "FAILED.The getLabel works wrong", "COMPLETED.OK". + */ + @Override + public String toString() { + String str = getRunStateString() + "." + getStateString(); + + return str; + } + + /** + * Checks whether the status runstate is completed. + */ + public boolean isCompleted() { + return getRunState() == RunState.COMPLETED; + } + + /** + * Checks whether the status state is failed. + */ + public boolean isFailed() { + return !isSuccessful(); + } + +} diff --git a/qadevOOo/runner/lib/StatusException.java b/qadevOOo/runner/lib/StatusException.java new file mode 100644 index 000000000..98ca686af --- /dev/null +++ b/qadevOOo/runner/lib/StatusException.java @@ -0,0 +1,65 @@ +/* + * 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 lib; + +/** + * StatusException is used to pass a Status object from a test code which is + * terminated abnormally. In many cases this is because of an exception thrown, + * but that can also be any other event that hinders the test execution. + */ +public class StatusException extends RuntimeException { + /** + * The Status contained in the StatusException. + */ + private final Status status; + + /** + * Constructs a StatusException containing an exception Status. + * + * @param message the message of the StatusException + * @param t the exception of the exception Status + */ + public StatusException( String message, Throwable t ) { + super( message, t ); + status = Status.exception( t ); + } + + /** + * Constructs a StatusException containing an exception Status. + */ + public StatusException( Throwable t, Status st ) { + super( t ); + this.status = st; + } + + /** + * Creates a StatusException containing a Status. + */ + public StatusException( Status st ) { + super( st.getRunStateString() ); + status = st; + } + + /** + * @return a status contained in the StatusException. + */ + public Status getStatus() { + return status; + } +} diff --git a/qadevOOo/runner/lib/TestCase.java b/qadevOOo/runner/lib/TestCase.java new file mode 100644 index 000000000..e5a628a2a --- /dev/null +++ b/qadevOOo/runner/lib/TestCase.java @@ -0,0 +1,170 @@ +/* + * 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 lib; + +import java.io.PrintWriter; + +/** + * <code>TestCase</code> represent a factory for <code>TestEnvironment</code>s + * creation and disposing for a given implementation object. The + * <code>TestEnvironment</code> contains an instance of the implementation + * object and all additional objects needed to perform tests on the object. + * + * <p>The <code>TestCase</code> provides four methods for its subclasses to + * define its functionality: <code>initialize()</code>, <code>cleanup()</code>, + * <code>createTestEnvironment()</code> and <code>disposeTestEnvironment()</code>. + * The first two are intended to initialize and cleanup common objects shared + * among all instances of <code>TestEnvironment</code> produced by the + * <code>TestCase</code>, and they are called at the beginning and at the end of + * the <code>TestCase</code> lifecycle accordingly. + * + * <p>The other two are intended to produce and dispose + * <code>TestEnvironment</code> instances. The + * <code>createTestEnvironment()</code> is called to create a + * <code>TestEnvironment</code> instance and the + * <code>disposeTestEnvironment()</code> is called when the instance is not used + * anymore. + * + * @see lib.TestEnvironment + */ +public abstract class TestCase { + + /** + * Specifies the PrintWriter to log information. + */ + protected PrintWriter log; + + /** + * Sets the log to write information during testing. + */ + public void setLogWriter( PrintWriter log ) { + this.log = log; + } + + /** + * Initializes the <code>TestCase</code>. Calls <code>initialize()</code> + * method. + * + * @param tParam test parameters. + */ + public final void initializeTestCase( TestParameters tParam ) throws Exception { + initialize( tParam, log ); + } + + /** + * Called while the <code>TestCase</code> initialization. In the + * implementation does nothing. Subclasses can override to initialize + * objects shared among all <code>TestEnvironment</code>s. + * + * @param tParam test parameters + * @param log writer to log information while testing + * + * @see #initializeTestCase + */ + protected void initialize( TestParameters tParam, PrintWriter log ) throws Exception { + } + + + /** + * Cleans up the <code>TestCase</code>. Calls <code>cleanup()</code>. + * + * @param tParam test parameters + */ + public final void cleanupTestCase( TestParameters tParam ) { + cleanup( tParam, log ); + } + + /** + * Called while the <code>TestCase</code> cleanup. In the implementation + * does nothing. Subclasses can override to cleanup objects shared among + * all <code>TestEnvironment</code>s. + * + * @param tParam test parameters + * @param log writer to log information while testing + * + * @see #cleanupTestCase + */ + protected void cleanup( TestParameters tParam, PrintWriter log ) { + } + + /** + * Creates a <code>TestEnvironment</code> containing an instance of the + * implementation object and related objects needed to perform test. + * + * @param tParam test parameters + * + * @return the created <code>TestEnvironment</code> + * + * @see #createTestEnvironment + * @see lib.TestEnvironment + */ + public synchronized TestEnvironment getTestEnvironment( TestParameters tParam ) { + TestEnvironment tEnv = null; + try { + tEnv = createTestEnvironment( tParam, log ); + System.out.println("Environment created"); + if (tEnv != null) { + tEnv.setTestCase(this); + } + } catch (Exception e) { + String message = e.getMessage(); + if (message == null) + message = e.toString(); + System.out.println("Exception while getting Environment "+message); + e.printStackTrace(); + cleanup(tParam, log); + } + return tEnv; + } + + /** + * Disposes the <code>TestEnvironment</code> when it is not needed anymore. + * + * @param tEnv the environment to dispose + * @param tParam test parameters + */ + public synchronized void disposeTestEnvironment( TestEnvironment tEnv, + TestParameters tParam ) { + cleanup( tParam, log ); + } + + /** + * Called to create an instance of <code>TestEnvironment</code> with an + * object to test and related objects. Subclasses should implement this + * method to provide the implementation and related objects. The method is + * called from <code>getTestEnvironment()</code>. + * + * @param tParam test parameters + * @param log writer to log information while testing + * + * @see TestEnvironment + * @see #getTestEnvironment + */ + protected abstract TestEnvironment createTestEnvironment( + TestParameters tParam, PrintWriter log ) throws Exception; + + /** + * @return the name of the object + */ + public String getObjectName() { + String clName = this.getClass().getName(); + return clName.substring( clName.lastIndexOf('.') + 1 ); + } + +} diff --git a/qadevOOo/runner/lib/TestEnvironment.java b/qadevOOo/runner/lib/TestEnvironment.java new file mode 100644 index 000000000..bba50c18f --- /dev/null +++ b/qadevOOo/runner/lib/TestEnvironment.java @@ -0,0 +1,132 @@ +/* + * 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 lib; +import com.sun.star.uno.XInterface; + +import java.util.HashMap; + + +/** + * The class contains an instance of a given implementation object and + * auxiliary objects associated with it and required for the object testing. + * + * @see TestCase + */ + +public final class TestEnvironment { + /** + * Contains object relations - auxiliary objects associated with the + * tested object and required for testing. + */ + private final HashMap<String, Object> relations = new HashMap<String, Object>(10); + + /** + * An instance of the tested implementation object. + */ + private final XInterface testObject; + + /** + * Indicates that the testObject is in invalid state and should not be + * used for testing anymore. + */ + private boolean disposed = false; + + /** + * A reference to TestCase which has created the test environment. + */ + private TestCase tCase; + + /** + * Creates an instance of test environment with testObject. + * + * @param testObject object to test + * + * @throws java.lang.IllegalArgumentException if the testObject is + * <tt>null</tt>. + */ + public TestEnvironment( XInterface testObject ) { + if (testObject == null) { + throw new IllegalArgumentException( + "Couldn't create a test object"); + } + this.testObject = testObject; + } + + /** + * @return the object to test. + */ + public XInterface getTestObject() { + return testObject; + } + + /** + * Adds to the environment an auxiliary object required for testing. + * + * @param name a name to reference the auxiliary object + * + * @param relation the auxiliary object related to the tested one + */ + public void addObjRelation( String name, Object relation) { + relations.put( name, relation ); + } + + /** + * Returns an auxiliary object referenced by tname. + * + * @param name a name of the object relation + * + * @return the auxiliary object(object relation) + */ + public Object getObjRelation( String name ) { + return relations.get( name ); + } + + /** + * Sets the <code>TestCase</code> that created the environment. + */ + public void setTestCase( TestCase tCase) { + this.tCase = tCase; + } + + /** + * @return the <code>TestCase</code> created the environment. + */ + public TestCase getTestCase() { + return tCase; + } + + /** + * Makes the environment invalid, i.e. it should not be used for + * testing anymore. + */ + public void dispose() { + disposed = true; + } + + /** + * Checks if the environment has been disposed. + * + * @return <tt>true</tt< if it has been disposed, <tt>false</tt> otherwise. + * + * @see #dispose() + */ + public boolean isDisposed() { + return disposed; + } +} diff --git a/qadevOOo/runner/lib/TestParameters.java b/qadevOOo/runner/lib/TestParameters.java new file mode 100644 index 000000000..04467a9c8 --- /dev/null +++ b/qadevOOo/runner/lib/TestParameters.java @@ -0,0 +1,206 @@ +/* + * 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 lib; + +import java.util.HashMap; + +import util.PropertyName; + +import com.sun.star.beans.XPropertySet; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.uno.XComponentContext; + +/** + * TestParameters describes a parameters (in a form of pairs: name, value) to + * be passed to tests and which may affect the test behaviour. That can be, + * for example, standard paths, connection strings, etc. The TestParameters + * also provides XMultiServiceFactory for the test (tests). + */ +public class TestParameters extends HashMap<String,Object> { + + /** + * The ConnectionString for Office Connection<br> + * default is 'socket,host=localhost,port=8100' + */ + private static final String DefaultConnectionString = "socket,host=localhost,port=8100"; + + /** + * The Path to the test documents that are loaded during the test <br> + */ + private static final String DefaultTestDocumentPath = "unknown"; + + /** + * 'true' is a debug information should be written, 'false' elsewhere + * these will be provided by the framework.<br> + * Debug information will always be written on standard out.<br> + * default is true + */ + private static final boolean DebugIsActive = false; + + /** + * Wrapper around "get()" with some debug output + * @param key A key of this table. + * @return The value of this key. + * @see java.util.HashMap + */ + @Override + public Object get(Object key) { + Object val = super.get(key); + if (val == null && DebugIsActive) { + System.out.print("Have been asked for key \""+key.toString()); + System.out.println("\" which is not part of params."); + } + return val; + } + + /** + * Special get method for boolean values: for convenience. + * Will return 'false' if the value is not of "Boolean" type. + * @param key A key of this table. + * @return The value of this key, cast to a boolean type. + */ + public boolean getBool(Object key) { + final Object val = super.get(key); + if (val == null) { + return false; + } + if (val instanceof String) { + String sVal = (String)val; + if (sVal.equalsIgnoreCase("true") || + sVal.equalsIgnoreCase("yes")) { + return true; + } + else if (sVal.equalsIgnoreCase("false") || + sVal.equalsIgnoreCase("no")) { + return false; + } + } + else if (val instanceof Boolean) + return ((Boolean)val).booleanValue(); + return false; + } + + /** + * Special get method for integer values: for convenience. + * Will return 0 if the value cannot be interpreted as Integer. + * @param key A key of this table. + * @return The value of this key, cast to an int type. + */ + public int getInt(Object key) { + Object val = super.get(key); + if ( val != null ) { + if (val instanceof Integer) { + return ((Integer)val).intValue(); + } + else { + try { + if ( val instanceof String ) { + Integer nr = Integer.valueOf((String)val); + if (nr.intValue() > 0) return nr.intValue(); + } + } catch ( java.lang.NumberFormatException nfe) {} + } + } + return 0; + } + + + /** + * Wrapper around "put()" + * @param key A key of this table. + * @param val The value of the key. + * @return The value of this key. + * @see java.util.HashMap + */ + @Override + public Object put(String key, Object val) { + return super.put(key,val); + } + + /** + * Constructor, defaults for Parameters are set. + */ + public TestParameters() { + //fill the propertyset + String user = System.getProperty("user.name"); + if ( user != null) + { + String PipeConnectionString = "pipe,name=" + user; + put(PropertyName.PIPE_CONNECTION_STRING,PipeConnectionString); + put(PropertyName.USE_PIPE_CONNECTION, Boolean.TRUE); + } + put(PropertyName.CONNECTION_STRING, DefaultConnectionString); + put(PropertyName.TEST_BASE, "java_fat"); + put(PropertyName.TEST_DOCUMENT_PATH, DefaultTestDocumentPath); + put(PropertyName.LOGGING_IS_ACTIVE, Boolean.TRUE); + put(PropertyName.DEBUG_IS_ACTIVE, Boolean.valueOf(DebugIsActive)); + put(PropertyName.OUT_PRODUCER, "stats.SimpleOutProducer"); + put(PropertyName.OFFICE_PROVIDER, "helper.OfficeProvider"); + put(PropertyName.LOG_WRITER, "stats.SimpleLogWriter"); + put(PropertyName.APP_EXECUTION_COMMAND, ""); + put(PropertyName.TIME_OUT, Integer.valueOf(3000000)); + put(PropertyName.THREAD_TIME_OUT, Integer.valueOf(3000000)); + put(PropertyName.AUTO_RESTART, Boolean.FALSE); + + // get the operating system + put(PropertyName.UNORC_NAME, getUnoRcName()); + + //For compatibility Reasons + System.setProperty("DOCPTH", DefaultTestDocumentPath); + } + + /** + * @return a XMultiServiceFactory to be used by a test (tests). + */ + public XMultiServiceFactory getMSF() { + Object ret = null; + ret = get("ServiceFactory"); + return (XMultiServiceFactory) ret; + } + + public XComponentContext getComponentContext() { + Object context = get( "ComponentContext" ); + if ( context == null ) + { + XPropertySet factoryProps = com.sun.star.uno.UnoRuntime.queryInterface( + XPropertySet.class, getMSF() ); + try + { + context = com.sun.star.uno.UnoRuntime.queryInterface( + XComponentContext.class, factoryProps.getPropertyValue( "DefaultContext" ) ); + put( "ComponentContext", context ); + } + catch( com.sun.star.beans.UnknownPropertyException e ) { } + catch( com.sun.star.lang.WrappedTargetException e ) { } + } + return (XComponentContext)context; + } + + /** + * @return The uno rc file name uno.ini for windows and unorc for everything else + */ + private String getUnoRcName() { + String osname = System.getProperty ("os.name").toLowerCase (); + if (osname.indexOf ("windows")>-1) { + return "uno.ini"; + } + return "unorc"; + } + +}// finish class TestParameters diff --git a/qadevOOo/runner/lib/TestResult.java b/qadevOOo/runner/lib/TestResult.java new file mode 100644 index 000000000..5a1f4898b --- /dev/null +++ b/qadevOOo/runner/lib/TestResult.java @@ -0,0 +1,88 @@ +/* + * 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 lib; + +import java.util.HashMap; + +/** + * The class supports interface tests development and Status calculation. + */ +public class TestResult { + /** + * Contains methods having been tested and their results. + */ + private HashMap<String, Status> testedMethods = new HashMap<String, Status>(); + + /** + * The method makes method tested with the result, i.e. it adds to its + * state OK (if result == true) or FAILED (if result == false) status + * and makes the state of the method completed. It's equal to + * tested(method, Status(result)) call. + * + * @param method refers to the method which was tested + * @param result the result of testing the method + * + * @return the result value + * + * @throw java.lang.IllegalArgumentException if the method is not + * available in the interface. + * + * @see #tested(String, Status) + */ + public boolean tested( String method, boolean result) { + System.out.println("Method "+method+" finished with state "+(result?"OK":"FAILED")); + return tested( method, Status.passed( result ) ); + } + + /** + * The method makes the method tested with the status, i.e. it adds the + * status to its state and makes it completed. + * + * @param method refers to the method which was tested + * @param status describes the result of testing the method + * @return <tt>true</tt> if status is OK, <tt>false</tt> otherwise. + * + * @throw java.lang.IllegalArgumentException if the method is not + * available in the interface. + */ + public boolean tested( String method, Status status ) { + testedMethods.put(method,status); + return true; + } + + /** + * @return <tt>true</tt> if the method belongs to the interface tested, + * <tt>false</tt> otherwise. + */ + public boolean hasMethod( String method ) { + return testedMethods.containsKey( method ); + } + + /** + * @return status of testing the method, if it is available (was set by + * the tested or assert method), <tt>null</tt> otherwise. + * + * @see #tested(String, boolean) + * @see #tested(String, Status) + */ + public Status getStatusFor( String method ) { + return testedMethods.get( method ); + } + +} diff --git a/qadevOOo/runner/manifest b/qadevOOo/runner/manifest new file mode 100644 index 000000000..9bebd71a2 --- /dev/null +++ b/qadevOOo/runner/manifest @@ -0,0 +1,2 @@ +RegistrationClassName: org.openoffice.RunnerService + diff --git a/qadevOOo/runner/org/openoffice/Runner.java b/qadevOOo/runner/org/openoffice/Runner.java new file mode 100644 index 000000000..7f839bead --- /dev/null +++ b/qadevOOo/runner/org/openoffice/Runner.java @@ -0,0 +1,196 @@ +/* + * 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 org.openoffice; + +import helper.ClParser; + +import java.util.Enumeration; +import java.util.Map; +import java.util.Properties; +import java.util.StringTokenizer; + +import lib.TestParameters; +import util.DynamicClassLoader; +import base.TestBase; + +/** + * The main class, will call ClParser and CfgParser to <br> + * fill the TestParameters.<br> + * Will then call the appropriate Testbase to run the tests. + */ +public class Runner +{ + + private static String beautifyTime(long _nTime) + { + long sec = (_nTime / 1000) % 60; + long min = (_nTime / (60 * 1000)) % 60; + long hour = _nTime / (60 * 60 * 1000); + StringBuffer aTime = new StringBuffer(); + aTime.append(helper.StringHelper.createValueString((int) hour, 2)). + append(':'). + append(helper.StringHelper.createValueString((int) min, 2)). + append(':'). + append(helper.StringHelper.createValueString((int) sec, 2)); + return aTime.toString(); + } + + /** + * Helper to check if there are problems with Cygwin Path variables. + */ + private static boolean checkVariableForCygwin(String _sVariable) + { + if (_sVariable == null) + { + return false; + } + return _sVariable.startsWith("/cygdrive"); + } + + private static boolean checkPathVariable(String _sPath, String delim) + { + String sPath = System.getProperty(_sPath); + if (sPath != null) + { + StringTokenizer aTokenEnum = new StringTokenizer(sPath, delim); + while (aTokenEnum.hasMoreElements()) + { + String sToken = (String) aTokenEnum.nextElement(); + if (checkVariableForCygwin(sToken)) + { + System.err.println("ERROR: OOoRunner detect cygwin path in '" + _sPath + "'"); + return true; + } + } + } + return false; + } + + private static void checkAllVariablesForCygwinPath(TestParameters _aParams) + { + // ----- check all System.getProperty(key) variables ----- + String sOsName = System.getProperty("os.name"); + if (!sOsName.toLowerCase().startsWith("windows")) + { + // we need to check only on windows + return; + } + + Properties aProps = System.getProperties(); + Enumeration<?> aEnum = aProps.propertyNames(); + // Enumeration aEnum = aProps.elements(); // these are only the values + boolean bEmergencyStop = false; + + while (aEnum.hasMoreElements()) + { + String sKey = (String) aEnum.nextElement(); + String sValue = System.getProperty(sKey); + + if (checkVariableForCygwin(sValue)) + { + System.err.println("ERROR: OOoRunner detect cygwin path in '" + sKey + ":=" + sValue + "'"); + bEmergencyStop = true; + } + } + + // ----- check path variables separately ----- + String sDelim = System.getProperty("path.separator"); + bEmergencyStop |= checkPathVariable("java.library.path", sDelim); + bEmergencyStop |= checkPathVariable("java.class.path", sDelim); + bEmergencyStop |= checkPathVariable("sun.boot.class.path", sDelim); + + // ----- check all TestParameters ----- + for (Map.Entry<String, Object> entry : _aParams.entrySet()) + { + String sKey = entry.getKey(); + if (entry.getValue() instanceof String) + { + String sValue = (String) entry.getValue(); + + if (checkVariableForCygwin(sValue)) + { + System.err.println("ERROR: OOoRunner detect cygwin path in '" + sKey + ":=" + sValue + "'"); + bEmergencyStop = true; + } + } + } + + if (bEmergencyStop) + { + System.exit(-1); + } + } + + public static boolean run(String... args) throws Exception + { + System.out.println("OOoRunner Main() version from 20101118 (yyyymmdd)"); + + final long nStartTime = System.currentTimeMillis(); + + DynamicClassLoader dcl = new DynamicClassLoader(); + + // get a class for test parameters + TestParameters param = new TestParameters(); + + ClParser cli = new ClParser(); + + //parse the commandline arguments + // TODO: no right error message, if no parameter given! + cli.getCommandLineParameter(param, args); + + Object tj = param.get("TestJob"); + + if (tj == null) + { + System.out.println("=========================================================================="); + System.out.println("No TestJob given, please make sure that you "); + System.out.println("a.) called the OOoRunner with the parameter -o <job> or -sce <scenarioFile>"); + System.out.println("or"); + System.out.println("b.) have an entry called TestJob in your used properties file"); + System.out.println("=========================================================================="); + System.exit(-1); + } + + System.out.println("TestJob: " + tj); + String sName = "base." + (String) param.get("TestBase"); + TestBase toExecute = (TestBase) dcl.getInstance(sName); + + checkAllVariablesForCygwinPath(param); + + boolean worked = toExecute.executeTest(param); + final long nTime = System.currentTimeMillis() - nStartTime; + final String sBeautifyTime = beautifyTime(nTime); + + System.out.println("Job run took: " + nTime + "ms " + " [" + sBeautifyTime + "]"); + + if (!worked) + { + System.out.println("Job " + param.get("TestJob") + " failed"); + } + else + { + System.out.println("Job " + param.get("TestJob") + " done"); + } + return worked; + } + + public static void main(String[] args) throws Exception + { + System.exit(run(args) ? 0 : -1); + } +} diff --git a/qadevOOo/runner/org/openoffice/RunnerService.java b/qadevOOo/runner/org/openoffice/RunnerService.java new file mode 100644 index 000000000..f61638c47 --- /dev/null +++ b/qadevOOo/runner/org/openoffice/RunnerService.java @@ -0,0 +1,301 @@ +/* + * 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 org.openoffice; + +import helper.ClParser; + +import java.util.ArrayList; +import java.util.jar.JarEntry; + +import lib.TestParameters; +import share.LogWriter; +import stats.InternalLogWriter; +import util.DynamicClassLoader; +import util.PropertyName; +import base.TestBase; + +import com.sun.star.beans.NamedValue; +import com.sun.star.beans.PropertyValue; +import com.sun.star.beans.XPropertyAccess; +import com.sun.star.comp.loader.FactoryHelper; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.lang.XSingleServiceFactory; +import com.sun.star.lang.XTypeProvider; +import com.sun.star.registry.XRegistryKey; +import com.sun.star.task.XJob; +import com.sun.star.uno.Type; +import com.sun.star.uno.XInterface; + +/** + * The main class, will call ClParser and CfgParser to <br> + * fill the TestParameters.<br> + * Will then call the appropriate Testbase to run the tests. + */ +public class RunnerService implements XJob, XServiceInfo, + XTypeProvider, XPropertyAccess { + + public static final String __serviceName = "org.openoffice.Runner"; + public static final String __implName = "org.openoffice.RunnerService"; + private static XMultiServiceFactory xMSF = null; + + public Object execute(NamedValue[] args) { + // construct valid arguments from the given stuff + int arg_length=args.length; + String[] arguments = new String[arg_length*2]; + for ( int i=0; i< arg_length; i++ ) { + arguments[i*2] = args[i].Name; + Object o = args[i].Value; + arguments[i*2+1] = o.toString(); + } + + TestParameters param = new TestParameters(); + DynamicClassLoader dcl = new DynamicClassLoader(); + + + // take the standard log writer + String standardLogWriter = (String) param.get(PropertyName.LOG_WRITER); + String standardOutProducer = (String) param.get(PropertyName.OUT_PRODUCER); + + ClParser cli = new ClParser(); + + //parse the commandline arguments + cli.getCommandLineParameter(param,arguments); + + // now compare the standard log writer with the parameters: + // if we have a new one, use the new, else use the internal + // log writer + if (((String)param.get("LogWriter")).equals(standardLogWriter)) + param.put("LogWriter", "stats.InternalLogWriter"); + if (((String)param.get("OutProducer")).equals(standardOutProducer)) + param.put("OutProducer", "stats.InternalLogWriter"); + LogWriter log = (LogWriter) dcl.getInstance( + (String)param.get("LogWriter")); + + param.put("ServiceFactory", xMSF); + + log.println("TestJob: "+param.get("TestJob")); + + TestBase toExecute = (TestBase)dcl.getInstance("base.java_fat_service"); + + try { + boolean worked = toExecute.executeTest(param); + if (!worked) + log.println("Test did not execute correctly."); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + + String returnString = ""; + if (log instanceof InternalLogWriter) + returnString = ((InternalLogWriter)log).getLog(); + return returnString; + } + + /** + * This function provides the service name + * @return the service name + */ + public String getServiceName() { + return __serviceName; + } + + /** + * Get all implemented types of this class. + * @return An array of implemented interface types. + * @see com.sun.star.lang.XTypeProvider + */ + public Type[] getTypes() { + Type[] type = new Type[5]; + type[0] = new Type(XInterface.class); + type[1] = new Type(XTypeProvider.class); + type[2] = new Type(XJob.class); + type[3] = new Type(XServiceInfo.class); + type[4] = new Type(XPropertyAccess.class); + return type; + } + + /** + * Get the implementation id. + * @return An empty implementation id. + * @see com.sun.star.lang.XTypeProvider + */ + public byte[] getImplementationId() { + return new byte[0]; + } + /** + * Function for reading the implementation name. + * + * @return the implementation name + * @see com.sun.star.lang.XServiceInfo + */ + public String getImplementationName() { + return __implName; + } + + /** + * Does the implementation support this service? + * + * @param serviceName The name of the service in question + * @return true, if service is supported, false otherwise + * @see com.sun.star.lang.XServiceInfo + */ + public boolean supportsService(String serviceName) { + return serviceName.equals(__serviceName); + } + + /** + * Function for reading all supported services + * + * @return An aaray with all supported service names + * @see com.sun.star.lang.XServiceInfo + */ + public String[] getSupportedServiceNames() { + String[] supServiceNames = {__serviceName}; + return supServiceNames; + } + + /** + * Return all valid testcases from the object descriptions + * @return The valid testcases as property values + */ + public PropertyValue[] getPropertyValues() { + PropertyValue[] pVal = null; + java.net.URL url = this.getClass().getResource("/objdsc"); + if (url == null) { + pVal = new PropertyValue[1]; + pVal[0] = new PropertyValue(); + pVal[0].Name = "Error"; + pVal[0].Value = "OOoRunner.jar file doesn't contain object " + + "descriptions: don't know what to test."; + return pVal; + } + + ArrayList<String> v = new ArrayList<String>(600); + try { + // open connection to Jar + java.net.JarURLConnection con = + (java.net.JarURLConnection)url.openConnection(); + // get Jar file from connection + java.util.jar.JarFile f = con.getJarFile(); + // Enumerate over all entries + java.util.Enumeration<JarEntry> aEnum = f.entries(); + + while (aEnum.hasMoreElements()) { + String entry = aEnum.nextElement().toString(); + if (entry.endsWith(".csv")) { + + String module = null; + String object = null; + + int startIndex = entry.indexOf("objdsc/") + 7; + int endIndex = entry.lastIndexOf('/'); + module = entry.substring(startIndex, endIndex); + + // special cases + if (entry.indexOf("/file/") != -1 || entry.indexOf("/xmloff/") != -1) { + endIndex = entry.indexOf(".csv"); + object = entry.substring(0, endIndex); + endIndex = object.lastIndexOf('.'); + startIndex = object.indexOf('.'); + while (startIndex != endIndex) { + object = object.substring(startIndex+1); + startIndex = object.indexOf('.'); + endIndex = object.lastIndexOf('.'); + } + } + else { + startIndex = 0; + endIndex = entry.indexOf(".csv"); + object = entry.substring(startIndex, endIndex); + startIndex = object.lastIndexOf('.'); + object = object.substring(startIndex+1); + } + v.add(module+"."+object); + } + } + } + catch(java.io.IOException e) { + e.printStackTrace(); + } + + int size = v.size(); + + String[] sTestCases = new String[size]; + v.toArray(sTestCases); + java.util.Arrays.sort(sTestCases); + + pVal = new PropertyValue[size]; + for (int i=0; i<size; i++) { + pVal[i] = new PropertyValue(); + pVal[i].Name = "TestCase"+i; + pVal[i].Value = sTestCases[i]; + } + return pVal; + } + + + /** + * + * Gives a factory for creating the service. + * This method is called by the <code>JavaLoader</code> + * <p> + * @return returns a <code>XSingleServiceFactory</code> for creating the component + * @param implName the name of the implementation for which a service is desired + * @param multiFactory the service manager to be used if needed + * @param regKey the registryKey + * @see com.sun.star.comp.loader.JavaLoader + */ + public static XSingleServiceFactory __getServiceFactory(String implName, + XMultiServiceFactory multiFactory, XRegistryKey regKey) + { + XSingleServiceFactory xSingleServiceFactory = null; + + if (implName.equals(RunnerService.class.getName())) + xSingleServiceFactory = FactoryHelper.getServiceFactory( + RunnerService.class, __serviceName, multiFactory, regKey); + xMSF = multiFactory; + return xSingleServiceFactory; + } + + /** + * Writes the service information into the given registry key. + * This method is called by the <code>JavaLoader</code> + * <p> + * @return returns true if the operation succeeded + * @param regKey the registryKey + * @see com.sun.star.comp.loader.JavaLoader + */ + public static boolean __writeRegistryServiceInfo(XRegistryKey regKey) { + return FactoryHelper.writeRegistryServiceInfo(RunnerService.class.getName(), + __serviceName, regKey); + } + + /** + * empty: not needed here. + */ + public void setPropertyValues(PropertyValue[] propertyValue) + throws com.sun.star.beans.UnknownPropertyException, + com.sun.star.beans.PropertyVetoException, + com.sun.star.lang.IllegalArgumentException, + com.sun.star.lang.WrappedTargetException { + // empty implementation + } + +} diff --git a/qadevOOo/runner/share/ComplexTest.java b/qadevOOo/runner/share/ComplexTest.java new file mode 100644 index 000000000..d5eea53a1 --- /dev/null +++ b/qadevOOo/runner/share/ComplexTest.java @@ -0,0 +1,28 @@ +/* + * 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 share; + +/** + * Interface for complex tests. + */ +public interface ComplexTest { + + String[] getTestMethodNames(); + +} + diff --git a/qadevOOo/runner/share/DescEntry.java b/qadevOOo/runner/share/DescEntry.java new file mode 100644 index 000000000..927715342 --- /dev/null +++ b/qadevOOo/runner/share/DescEntry.java @@ -0,0 +1,88 @@ +/* + * 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 share; + +/** + * + * Structure to describe the entries to be tested + * + */ +public class DescEntry { + + /** + * Contains the name used inside the framework + */ + public String entryName; + /** + * Contains the name that may be used by state writers + */ + public String longName; + /** + * Contains information if this entry is Optional + */ + public boolean isOptional; + /** + * Contains information if this entry should be tested + */ + public boolean isToTest; + /** + * Contains the information about the number of SubEntries + */ + public int SubEntryCount; + /** + * Contains the SubEntries + */ + public DescEntry[] SubEntries; + + /** + * Contains information about the Type of the entry<br> + * possible 'component', 'interface', 'service', 'method', 'property', 'unit' + */ + public String EntryType; + + /** + * Contains the ErrorMsg is something went wrong while gaining<br> + * the description + */ + public String ErrorMsg; + + /** + * Contains information if errors occurred while gaining the Description + */ + public boolean hasErrorMsg; + + /** + * Contains the state for this entry + */ + public String State = "UNKNOWN"; + + /** + * Contains the LogWriter to be used by the entry-test + */ + + public share.LogWriter Logger; + + /** + * Contains an arbitrary set of parameters + */ + + public java.util.HashMap<String,Object> UserDefinedParams = new java.util.HashMap<String,Object>(); + +} diff --git a/qadevOOo/runner/share/DescGetter.java b/qadevOOo/runner/share/DescGetter.java new file mode 100644 index 000000000..172dcacf5 --- /dev/null +++ b/qadevOOo/runner/share/DescGetter.java @@ -0,0 +1,182 @@ +/* + * 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 share; + +import java.io.BufferedReader; +import java.io.FileReader; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.StringTokenizer; + +/** + * + * Base Interface to get a description for a given TestJob + * + */ +public abstract class DescGetter +{ + + public abstract DescEntry[] getDescriptionFor(String entry, + String DescPath, + boolean debug); + + protected abstract DescEntry getDescriptionForSingleJob(String job, + String descPath, + boolean debug); + + protected abstract String[] createScenario(String descPath, String job, + boolean debug); + + protected DescEntry[] getScenario(String url, String descPath, + boolean debug) + { + ArrayList<DescEntry> entryList = new ArrayList<DescEntry>(); + String line = ""; + BufferedReader scenario = null; + DescEntry[] entries = null; + + try + { + scenario = new BufferedReader(new FileReader(url)); + } + catch (java.io.FileNotFoundException fnfe) + { + System.out.println("Couldn't find file " + url); + + return entries; + } + + while (line != null) + { + try + { + if (line.startsWith("-o")) + { + String job = line.substring(3, line.length()).trim(); + DescEntry aEntry; + // special in case several Interfaces are given comma separated + if (job.indexOf(',') < 0) + { + aEntry = getDescriptionForSingleJob(job, descPath, + debug); + } + else + { + ArrayList<String> subs = getSubInterfaces(job); + String partjob = job.substring(0, job.indexOf(',')).trim(); + aEntry = getDescriptionForSingleJob(partjob, descPath, + debug); + + if (aEntry != null) + { + for (int i = 0; i < aEntry.SubEntryCount; i++) + { + String subEntry = aEntry.SubEntries[i].longName; + int cpLength = aEntry.longName.length(); + subEntry = subEntry.substring(cpLength + 2, + subEntry.length()); + + if (subs.contains(subEntry)) + { + aEntry.SubEntries[i].isToTest = true; + } + } + } + } + if (aEntry != null) + { + entryList.add(aEntry); + } + } + else if (line.startsWith("-sce")) + { + DescEntry[] subs = getScenario(line.substring(5, + line.length()).trim(), descPath, + debug); + + entryList.addAll(Arrays.asList(subs)); + } + else if (line.startsWith("-p")) + { + String[] perModule = createScenario(descPath, + line.substring(3).trim(), debug); + + for (int i = 0; i < perModule.length; i++) + { + DescEntry aEntry = getDescriptionForSingleJob( + perModule[i].substring(3).trim(), + descPath, debug); + if (aEntry != null) + { + entryList.add(aEntry); + } + } + } + + line = scenario.readLine(); + } + catch (java.io.IOException ioe) + { + if (debug) + { + System.out.println("Exception while reading scenario"); + } + } + } + + try + { + scenario.close(); + } + catch (java.io.IOException ioe) + { + if (debug) + { + System.out.println("Exception while closing scenario"); + } + } + + if (entryList.isEmpty()) + { + return null; + } + entries = new DescEntry[entryList.size()]; + entries = entryList.toArray(entries); + + return entries; + } + + 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; + } +} diff --git a/qadevOOo/runner/share/LogWriter.java b/qadevOOo/runner/share/LogWriter.java new file mode 100644 index 000000000..44d4a2b7d --- /dev/null +++ b/qadevOOo/runner/share/LogWriter.java @@ -0,0 +1,52 @@ +/* + * 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 share; + +public interface LogWriter { + + /** + * Method to print + */ + void println(String msg); + + /** + * initialization + * + */ + boolean initialize(share.DescEntry entry, boolean active); + + /** + * will mostly be used by outproducers to sum up + * the information, maybe write them to a db + */ + boolean summary(share.DescEntry entry); + + + + + /** + * Set a <CODE>Watcher</CODE> to the <CODE>LogWriter</CODE> + * This is useful if a test starts a new office instance by itself. In this cases + * the <CODE>LogWriter</CODE> could retrigger the <CODE>Watcher</CODE> + * @see share.Watcher + * @param watcher the new <CODE>Watcher</CODE> + */ + void setWatcher(Object watcher); + +} diff --git a/qadevOOo/runner/share/Watcher.java b/qadevOOo/runner/share/Watcher.java new file mode 100644 index 000000000..07e8e6562 --- /dev/null +++ b/qadevOOo/runner/share/Watcher.java @@ -0,0 +1,33 @@ +/* + * 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 share; + +public interface Watcher { + + /** + * pings the watcher to check for changes + */ + void ping(); + + /** + * returns the amount of pings + */ + int getPing(); + +} diff --git a/qadevOOo/runner/stats/InternalLogWriter.java b/qadevOOo/runner/stats/InternalLogWriter.java new file mode 100644 index 000000000..a39e372a6 --- /dev/null +++ b/qadevOOo/runner/stats/InternalLogWriter.java @@ -0,0 +1,101 @@ +/* + * 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 stats; + +import java.io.PrintWriter; +import java.io.StringWriter; + +/** + * Write all logs into a java.io.PrintWriter, i.e. a StringBuffer. + * Log is gathered there. + */ +public class InternalLogWriter implements share.LogWriter { + /** log active **/ + private boolean active; + /** write all output to a StringBuffer **/ + private StringWriter writer = new StringWriter(); + private PrintWriter printWriter; + + /** + * c'*tor + */ + public InternalLogWriter() { + printWriter = new PrintWriter(writer); + active = true; + } + + /** + * Initialization. + * @param entry The description entry. + * @param active Logging is active. + * @return True, if initialize worked. + */ + public boolean initialize(share.DescEntry entry, boolean active) { + this.active = active; + return true; + } + + /** + * Method to print a line that is added to the StringBuffer. + * @param msg The message that is printed. + */ + public void println(String msg) { + if (active) + printWriter.println(msg); + } + + /** + * Is used to sum up the information. + * The summary is also added to the StringBuffer. + * @param entry The description entry. + * @return True, if a summary could be created. + */ + public boolean summary(share.DescEntry entry) { +// linePrefix = ""; + String header = "***** State for "+entry.longName+" ******"; + printWriter.println(header); + if (entry.hasErrorMsg) { + printWriter.println(entry.ErrorMsg); + printWriter.println("Whole "+entry.EntryType+": "+entry.State); + } else { + printWriter.println("Whole "+entry.EntryType+": "+entry.State); + } + for (int i=0;i<header.length();i++) { + printWriter.print("*"); + } + printWriter.println(""); + return true; + } + + /** + * Return all the written stuff. + * @return All that was written to the StringBuffer with the + * 'println()', 'print()' and 'summarize()' methods. + * The StringBuffer is emptied afterwards. + **/ + public String getLog() { + String message = writer.getBuffer().toString(); + writer = new StringWriter(); + return message; + } + + public void setWatcher(Object watcher) { + } + +} + diff --git a/qadevOOo/runner/stats/OutProducerFactory.java b/qadevOOo/runner/stats/OutProducerFactory.java new file mode 100644 index 000000000..cb907a490 --- /dev/null +++ b/qadevOOo/runner/stats/OutProducerFactory.java @@ -0,0 +1,121 @@ +/* + * 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 stats; + +import share.LogWriter; +import java.util.HashMap; +import util.DynamicClassLoader; + +/** + * A factory class for creating out producers. + */ +public class OutProducerFactory { + + /** + * Create an out producer. The type that is created depends on the + * parameters given. These are: + * <ul> + * <li>DataBaseOut - If set to true, a database outproducer is created. + * <li>OutProducer - The value of this parameter names the class that is created. + * </ul> + * @param param Parameters of the test. + * @return The created out producer. + */ + public static LogWriter createOutProducer(HashMap<String,Object> param) { + LogWriter dbOut = null; + boolean getDatabase = convertToBool(param.get("DataBaseOut")); + if (getDatabase) { + dbOut = createDataBaseOutProducer(param); + } + if (dbOut == null) { + DynamicClassLoader dcl = new DynamicClassLoader(); + String outProducerName = (String)param.get("OutProducer"); + if (outProducerName != null) { + try { + dbOut = (LogWriter)dcl.getInstance(outProducerName); + } + catch(IllegalArgumentException e) { + e.printStackTrace(); + } + } + } + if (dbOut == null) { + dbOut = createSimpleOutProducer(); + } + return dbOut; + } + + /** + * Create a database out producer. + * @param param The test parameters + * @return The database out producer, or null if it couldn't be created. + */ + private static LogWriter createDataBaseOutProducer(HashMap<String,Object> param) { + String dataProducerName = (String)param.get("DataBaseOutProducer"); + if (dataProducerName == null) { + String testBaseName = (String)param.get("TestBase"); + dataProducerName = testBaseName.substring(testBaseName.indexOf('_')+1); + dataProducerName = "stats." + makeFirstCharUpperCase(dataProducerName) + + "DataBaseOutProducer"; + } + DynamicClassLoader dcl = new DynamicClassLoader(); + LogWriter dbOut = null; + try { + dbOut = (LogWriter)dcl.getInstance(dataProducerName, + new Class[]{HashMap.class}, new Object[]{param}); + } + catch(IllegalArgumentException e) { + e.printStackTrace(); + } + return dbOut; + } + + /** + * As a fallback, create a simple out producer, if all else failed. + * @return A simple out producer, writing to the screen. + */ + private static LogWriter createSimpleOutProducer() { + return new SimpleOutProducer(); + } + + private static boolean convertToBool(Object val) { + if(val != null) { + if ( val instanceof String ) { + String sVal = (String)val; + if ( sVal.equalsIgnoreCase("true") || sVal.equalsIgnoreCase("yes") ) { + return true; + } + + } + else if (val instanceof Boolean) { + return ((Boolean)val).booleanValue(); + } + } + return false; + } + + /** + * Make the first character to an upper case char. + * @param name The String to change + * @return The String with an upper case first char. + */ + private static String makeFirstCharUpperCase(String name) { + return name.substring(0,1).toUpperCase() + name.substring(1); + } + +} diff --git a/qadevOOo/runner/stats/SimpleLogWriter.java b/qadevOOo/runner/stats/SimpleLogWriter.java new file mode 100644 index 000000000..46e18527b --- /dev/null +++ b/qadevOOo/runner/stats/SimpleLogWriter.java @@ -0,0 +1,94 @@ +/* + * 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 stats; + +import share.LogWriter; + +import java.io.PrintWriter; +import java.text.DecimalFormat; +import java.util.Calendar; +import java.util.GregorianCalendar; + +public class SimpleLogWriter extends PrintWriter implements LogWriter { + + private boolean m_bLogging = false; + private share.DescEntry entry = null; + private share.Watcher ow = null; + + public SimpleLogWriter() { + super(System.out); + Calendar cal = new GregorianCalendar(); + DecimalFormat dfmt = new DecimalFormat("00"); + super.println("LOG> Log started " + + dfmt.format(cal.get(Calendar.DAY_OF_MONTH)) + "." + + dfmt.format(cal.get(Calendar.MONTH)) + "." + + dfmt.format(cal.get(Calendar.YEAR)) + " - " + + dfmt.format(cal.get(Calendar.HOUR_OF_DAY)) + ":" + + dfmt.format(cal.get(Calendar.MINUTE)) + ":" + + dfmt.format(cal.get(Calendar.SECOND))); + super.flush(); + } + + public boolean initialize(share.DescEntry _entry, boolean _bLogging) { + m_bLogging = _bLogging; + entry = _entry; + + return true; + } + + @Override + public void println(String msg) { + if ((ow == null) && (entry != null)) + { + this.ow = (share.Watcher) entry.UserDefinedParams.get("Watcher"); + if (this.ow != null) + { + this.ow.ping(); + } + } + else + { + if (ow != null) + { + this.ow.ping(); + } + else + { + // special case: ow == null && entry == null + System.out.println(msg); + } + } + + if (m_bLogging) { + super.println("LOG> " + msg); + super.flush(); + } + } + + public boolean summary(share.DescEntry entry) { + return true; + } + + public void setWatcher(Object watcher) + { + if (watcher != null) + { + entry.UserDefinedParams.put("Watcher", watcher); + } + } +} diff --git a/qadevOOo/runner/stats/SimpleOutProducer.java b/qadevOOo/runner/stats/SimpleOutProducer.java new file mode 100644 index 000000000..93ca0503c --- /dev/null +++ b/qadevOOo/runner/stats/SimpleOutProducer.java @@ -0,0 +1,61 @@ +/* + * 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 stats; + +import share.LogWriter; + +public class SimpleOutProducer implements LogWriter { + + + /** initialization, here a filename might be given + * or a dbUrL + */ + public boolean initialize(share.DescEntry entry, boolean active) { + return true; + } + + /** Method to print + */ + public void println(String msg) { + + } + + /** will mostly be used by outproducers to sum up + * the information, maybe write them to a db + */ + public boolean summary(share.DescEntry entry) { + String header = "***** State for "+entry.longName+" ******"; + System.out.println(header); + if (entry.hasErrorMsg) { + System.out.println(entry.ErrorMsg); + System.out.println("Whole "+entry.EntryType+": "+entry.State); + } else { + System.out.println("Whole "+entry.EntryType+": "+entry.State); + } + for (int i=0;i<header.length();i++) { + System.out.print("*"); + } + System.out.println(""); + return true; + } + + public void setWatcher(Object watcher) { + } + +} diff --git a/qadevOOo/runner/stats/Summarizer.java b/qadevOOo/runner/stats/Summarizer.java new file mode 100644 index 000000000..36addd5e6 --- /dev/null +++ b/qadevOOo/runner/stats/Summarizer.java @@ -0,0 +1,104 @@ +/* + * 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 stats; + +import java.util.ArrayList; + +import share.DescEntry; + +/** + * + * this class adds up the results of the subentries of a given DescEntry + * and fills the subentries in cases of SKIPPED states + */ +public class Summarizer +{ + + /** + * + * gets the state for a SuperEntry according to its subentries + */ + public void summarizeUp(DescEntry entry) + { + if ((entry.State != null) && !entry.State.equals("UNKNOWN")) + { + return; + } + int count = entry.SubEntryCount; + int knownIssues = 0; + ArrayList<String> failures = new ArrayList<String>(); + ArrayList<String> states = new ArrayList<String>(); + for (int i = 0; i < count; i++) + { + if (entry.SubEntries[i].State == null) + { + entry.SubEntries[i].State = "COMPLETED.FAILED"; + } + if (entry.SubEntries[i].State.equals("known issue")) + { + entry.SubEntries[i].State = "COMPLETED.OK"; + knownIssues++; + } + if (!entry.SubEntries[i].State.endsWith("OK")) + { + String sFailure = "[" + entry.SubEntries[i].longName + "]" + " is testcode: [" + entry.SubEntries[i].entryName + "]"; + failures.add(sFailure); + states.add(entry.SubEntries[i].State); + } + } + if (failures.size() > 0) + { + StringBuilder errMsg = new StringBuilder(); + String state = "COMPLETED.FAILED"; + for (int j = 0; j < failures.size(); j++) + { + if (states.get(j).equals("not part of the job")) + { + state = "COMPLETED(some interfaces/services not tested).OK"; + } + else + { + errMsg.append(failures.get(j)).append(" - ").append(states.get(j)).append("\r\n"); + } + } + entry.hasErrorMsg = true; + entry.ErrorMsg = errMsg.toString(); + entry.State = state; + } + else if (entry.EntryType.equals("component") && knownIssues > 0) + { + entry.State = "COMPLETED(with known issues).OK"; + } + else + { + entry.State = "COMPLETED.OK"; + } + } + + public static void summarizeDown(DescEntry entry, String state) + { + if ((entry.State == null) || entry.State.equals("UNKNOWN")) + { + entry.State = state; + } + for (int i = 0; i < entry.SubEntryCount; i++) + { + summarizeDown(entry.SubEntries[i], entry.State); + } + } +} diff --git a/qadevOOo/runner/util/AccessibilityTools.java b/qadevOOo/runner/util/AccessibilityTools.java new file mode 100644 index 000000000..4426af496 --- /dev/null +++ b/qadevOOo/runner/util/AccessibilityTools.java @@ -0,0 +1,383 @@ +/* + * 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 util; + +import com.sun.star.accessibility.XAccessible; +import com.sun.star.accessibility.XAccessibleComponent; +import com.sun.star.accessibility.XAccessibleContext; +import com.sun.star.awt.XWindow; +import com.sun.star.frame.XController; +import com.sun.star.frame.XFrame; +import com.sun.star.frame.XModel; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XInterface; + +import java.io.PrintWriter; + + +public class AccessibilityTools { + public static XAccessible SearchedAccessible = null; + private static boolean debug = false; + + private AccessibilityTools() {} + + public static XAccessible getAccessibleObject(XInterface xObject) { + return UnoRuntime.queryInterface(XAccessible.class, xObject); + } + + public static XWindow getCurrentContainerWindow(XModel xModel) { + return getWindow(xModel, true); + } + + public static XWindow getCurrentWindow(XModel xModel) { + return getWindow(xModel, false); + } + + private static XWindow getWindow(XModel xModel, + boolean containerWindow) { + XWindow xWindow = null; + + try { + XController xController = xModel.getCurrentController(); + XFrame xFrame = xController.getFrame(); + + if (xFrame == null) { + System.out.println("can't get frame from controller"); + } else { + if (containerWindow) + xWindow = xFrame.getContainerWindow(); + else + xWindow = xFrame.getComponentWindow(); + } + + if (xWindow == null) { + System.out.println("can't get window from frame"); + } + } catch (Exception e) { + System.out.println("caught exception while getting current window" + e); + } + + return xWindow; + } + + public static XAccessibleContext getAccessibleObjectForRole(XAccessible xacc, + short role) { + SearchedAccessible = null; + return getAccessibleObjectForRole_(xacc, role); + } + + public static XAccessibleContext getAccessibleObjectForRole(XAccessible xacc, + short role, + boolean ignoreShowing) { + SearchedAccessible = null; + + if (ignoreShowing) { + return getAccessibleObjectForRoleIgnoreShowing_(xacc, role); + } else { + return getAccessibleObjectForRole_(xacc, role); + } + } + + private static XAccessibleContext getAccessibleObjectForRoleIgnoreShowing_(XAccessible xacc, + short role) { + XAccessibleContext ac = xacc.getAccessibleContext(); + if (ac == null) { + return null; + } + if (ac.getAccessibleRole() == role) { + SearchedAccessible = xacc; + return ac; + } else { + int k = ac.getAccessibleChildCount(); + + if (ac.getAccessibleChildCount() > 100) { + k = 50; + } + + for (int i = 0; i < k; i++) { + try { + XAccessibleContext ac2 = getAccessibleObjectForRoleIgnoreShowing_( + ac.getAccessibleChild(i), role); + + if (ac2 != null) { + return ac2; + } + } catch (com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Couldn't get Child"); + } + } + return null; + } + } + + private static XAccessibleContext getAccessibleObjectForRole_(XAccessible xacc, + short role) { + XAccessibleContext ac = xacc.getAccessibleContext(); + boolean isShowing = ac.getAccessibleStateSet() + .contains(com.sun.star.accessibility.AccessibleStateType.SHOWING); + + if ((ac.getAccessibleRole() == role) && isShowing) { + SearchedAccessible = xacc; + return ac; + } else { + int k = ac.getAccessibleChildCount(); + + if (ac.getAccessibleChildCount() > 100) { + k = 50; + } + + for (int i = 0; i < k; i++) { + try { + XAccessibleContext ac2 = getAccessibleObjectForRole_(ac.getAccessibleChild(i), role); + + if (ac2 != null) { + return ac2; + } + } catch (com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Couldn't get Child"); + } + } + return null; + } + } + + public static XAccessibleContext getAccessibleObjectForRole(XAccessible xacc, + short role, + String name) { + return getAccessibleObjectForRole(xacc, role, name, ""); + } + + public static XAccessibleContext getAccessibleObjectForRole(XAccessible xacc, + short role, + String name, + boolean ignoreShowing) { + if (ignoreShowing) { + return getAccessibleObjectForRoleIgnoreShowing(xacc, role, name, + ""); + } else { + return getAccessibleObjectForRole(xacc, role, name, ""); + } + } + + public static XAccessibleContext getAccessibleObjectForRoleIgnoreShowing(XAccessible xacc, + short role, + String name, + String implName) { + XAccessibleContext ac = xacc.getAccessibleContext(); + if ((ac.getAccessibleRole() == role) && + (ac.getAccessibleName().indexOf(name) > -1) && + (utils.getImplName(ac).indexOf(implName) > -1)) { + SearchedAccessible = xacc; + + return ac; + } else { + int k = ac.getAccessibleChildCount(); + + if (ac.getAccessibleChildCount() > 100) { + k = 50; + } + + for (int i = 0; i < k; i++) { + try { + XAccessibleContext ac1 = getAccessibleObjectForRoleIgnoreShowing( + ac.getAccessibleChild(i), + role, name, implName); + + if (ac1 != null) { + return ac1; + } + } catch (com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Couldn't get Child"); + } + } + } + + return null; + } + + public static XAccessibleContext getAccessibleObjectForRole(XAccessible xacc, + short role, + String name, + String implName) { + XAccessibleContext ac = xacc.getAccessibleContext(); + boolean isShowing = ac.getAccessibleStateSet() + .contains(com.sun.star.accessibility.AccessibleStateType.SHOWING); + + // hotfix for i91828: + // if role to search is 0 then ignore the role. + if ( (role == 0 || ac.getAccessibleRole() == role) && + (ac.getAccessibleName().indexOf(name) > -1) && + (utils.getImplName(ac).indexOf(implName) > -1) && + isShowing) { + SearchedAccessible = xacc; + return ac; + } else { + int k = ac.getAccessibleChildCount(); + + if (ac.getAccessibleChildCount() > 100) { + k = 50; + } + + for (int i = 0; i < k; i++) { + try { + XAccessibleContext ac1 = getAccessibleObjectForRole( + ac.getAccessibleChild(i), + role, name, implName); + + if (ac1 != null) { + return ac1; + } + } catch (com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Couldn't get Child"); + } + } + } + + return null; + } + + public static void printAccessibleTree(PrintWriter log, XAccessible xacc, boolean debugIsActive) { + debug = debugIsActive; + if (debug) printAccessibleTree(log, xacc, ""); + } + + public static void printAccessibleTree(PrintWriter log, XAccessible xacc) { + printAccessibleTree(log, xacc, ""); + } + + private static void printAccessibleTree(PrintWriter log, + XAccessible xacc, String indent) { + + XAccessibleContext ac = xacc.getAccessibleContext(); + + logging(log,indent + ac.getAccessibleRole() + "," + + ac.getAccessibleName() + "(" + + ac.getAccessibleDescription() + "):" + + utils.getImplName(ac)); + + XAccessibleComponent aComp = UnoRuntime.queryInterface( + XAccessibleComponent.class, xacc); + + if (aComp != null) { + String bounds = "(" + aComp.getBounds().X + "," + + aComp.getBounds().Y + ")" + " (" + + aComp.getBounds().Width + "," + + aComp.getBounds().Height + ")"; + bounds = "The boundary Rectangle is " + bounds; + logging(log,indent + indent + bounds); + } + + boolean isShowing = ac.getAccessibleStateSet() + .contains(com.sun.star.accessibility.AccessibleStateType.SHOWING); + logging(log,indent + indent + "StateType contains SHOWING: " + + isShowing); + + int k = ac.getAccessibleChildCount(); + + if (ac.getAccessibleChildCount() > 100) { + k = 50; + } + + for (int i = 0; i < k; i++) { + try { + printAccessibleTree(log, ac.getAccessibleChild(i), + indent + " "); + } catch (com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Couldn't get Child"); + } + } + + if (ac.getAccessibleChildCount() > 100) { + k = ac.getAccessibleChildCount(); + + int st = ac.getAccessibleChildCount() - 50; + logging(log,indent + " " + " ...... [skipped] ......"); + + for (int i = st; i < k; i++) { + try { + printAccessibleTree(log, ac.getAccessibleChild(i), + indent + " "); + } catch (com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Couldn't get Child"); + } + } + } + } + + public static String accessibleToString(Object AC) { + XAccessibleContext xAC = UnoRuntime.queryInterface( + XAccessibleContext.class, AC); + + if (xAC != null) { + return xAC.getAccessibleRole() + "," + + xAC.getAccessibleName() + "(" + + xAC.getAccessibleDescription() + "):"; + } + + XAccessible xA = UnoRuntime.queryInterface( + XAccessible.class, AC); + + if (xA == null) { + return "(Not supported)"; + } + + xAC = xA.getAccessibleContext(); + + return xAC.getAccessibleRole() + "," + xAC.getAccessibleName() + + "(" + xAC.getAccessibleDescription() + ")"; + } + + public static boolean equals(XAccessible c1, XAccessible c2) { + if ((c1 == null) || (c2 == null)) { + return c1 == c2; + } + + return AccessibilityTools.equals(c1.getAccessibleContext(), + c2.getAccessibleContext()); + } + + public static boolean equals(XAccessibleContext c1, XAccessibleContext c2) { + if ((c1 == null) || (c2 == null)) { + return c1 == c2; + } + + if (c1.getAccessibleRole() != c2.getAccessibleRole()) { + return false; + } + + if (!c1.getAccessibleName().equals(c2.getAccessibleName())) { + return false; + } + + if (!c1.getAccessibleDescription() + .equals(c2.getAccessibleDescription())) { + return false; + } + + if (c1.getAccessibleChildCount() != c2.getAccessibleChildCount()) { + return false; + } + + return AccessibilityTools.equals(c1.getAccessibleParent(), + c2.getAccessibleParent()); + } + + private static void logging(PrintWriter log, String content){ + if (debug) log.println(content); + } +} diff --git a/qadevOOo/runner/util/BookmarkDsc.java b/qadevOOo/runner/util/BookmarkDsc.java new file mode 100644 index 000000000..02736c9ba --- /dev/null +++ b/qadevOOo/runner/util/BookmarkDsc.java @@ -0,0 +1,73 @@ +/* + * 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 util; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.uno.XInterface; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.text.XTextContent; + +/** + * describes a Bookmark to be inserted in a container + */ +public class BookmarkDsc extends InstDescr { + + private static final String service = "com.sun.star.text.Bookmark"; + private static final String ifcName = "com.sun.star.text.XTextContent"; + + + public BookmarkDsc() { + initBookmark(); + } + + @Override + public String getName() { + return null; + } + + @Override + public String getIfcName() { + return ifcName; + } + + @Override + public String getService() { + return service; + } + + private void initBookmark() { + try { + ifcClass = Class.forName( ifcName ); + } + catch( ClassNotFoundException cnfE ) { + } + } + @Override + public XInterface createInstance( XMultiServiceFactory docMSF ) { + Object ServiceObj = null; + + try { + ServiceObj = docMSF.createInstance( service ); + } + catch( com.sun.star.uno.Exception cssuE ){ + } + XTextContent BM = (XTextContent)UnoRuntime.queryInterface( ifcClass, + ServiceObj ); + return BM; + } +} diff --git a/qadevOOo/runner/util/CalcTools.java b/qadevOOo/runner/util/CalcTools.java new file mode 100644 index 000000000..e9a84cdbc --- /dev/null +++ b/qadevOOo/runner/util/CalcTools.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 util; + +import com.sun.star.container.XIndexAccess; +import com.sun.star.lang.IllegalArgumentException; +import com.sun.star.lang.IndexOutOfBoundsException; +import com.sun.star.lang.WrappedTargetException; +import com.sun.star.lang.XComponent; +import com.sun.star.sheet.XCellRangeData; +import com.sun.star.sheet.XSpreadsheet; +import com.sun.star.sheet.XSpreadsheetDocument; +import com.sun.star.sheet.XSpreadsheets; +import com.sun.star.table.XCellRange; +import com.sun.star.uno.AnyConverter; +import com.sun.star.uno.Exception; +import com.sun.star.uno.Type; +import com.sun.star.uno.UnoRuntime; + +/** + * This class contains some useful methods to handle Calc documents + * and its sheets. + */ +public class CalcTools { + + /** + * fills a range of a calc sheet with computed data of type + * <CODE>Double</CODE>. + * @param xSheetDoc the Calc documents which should be filled + * @param sheetNumber the number of the sheet of <CODE>xSheetDoc</CODE> + * @param startCellX the cell number of the X start point (row) of the range to fill + * @param startCellY the cell number of the Y start point (column) of the range to fill + * @param rangeLengthX the size of the range expansion in X-direction + * @param rangeLengthY the size of the range expansion in Y-direction + * @throws java.lang.Exception on any error an <CODE>java.lang.Exception</CODE> was thrown + */ + public static void fillCalcSheetWithContent(XComponent xSheetDoc, int sheetNumber, + int startCellX, int startCellY, int rangeLengthX, int rangeLengthY) + throws java.lang.Exception { + XSpreadsheet xSheet = getSpreadSheetFromSheetDoc(xSheetDoc, sheetNumber); + + fillCalcSheetWithContent(xSheet, startCellX, startCellY, rangeLengthX, rangeLengthY); + } + + /** + * fills a range of a calc sheet with computed data of type + * <CODE>Double</CODE>. + * @param xSheet the sheet to fill with content + * @param startCellX the cell number of the X start point (row) of the range to fill + * @param startCellY the cell number of the Y start point (column) of the range to fill + * @param rangeLengthX the size of the range expansion in X-direction + * @param rangeLengthY the size of the range expansion in Y-direction + * @throws java.lang.Exception on any error an <CODE>java.lang.Exception</CODE> was thrown + */ + public static void fillCalcSheetWithContent(XSpreadsheet xSheet, + int startCellX, int startCellY, int rangeLengthX, int rangeLengthY) + throws java.lang.Exception { + // create a range with content + Object[][] newData = new Object[rangeLengthY][rangeLengthX]; + for (int i=0; i<rangeLengthY; i++) { + for (int j=0; j<rangeLengthX; j++) { + newData[i][j] = new Double(10*i +j); + } + } + XCellRange xRange = null; + try { + xRange = xSheet.getCellRangeByPosition(startCellX, startCellY, + startCellX+rangeLengthX-1, startCellY+rangeLengthY-1); + } catch ( IndexOutOfBoundsException ex){ + throw new Exception(ex, "Couldn't get CellRange from sheet"); + } + + XCellRangeData xRangeData = UnoRuntime.queryInterface(XCellRangeData.class, xRange); + + xRangeData.setDataArray(newData); + } + + /** + * + * returns an <CODE>XSpreadsheet</CODE> from a Calc document. + * @param xSheetDoc the Calc document which contains the sheet + * @param sheetNumber the number of the sheet to return + * @throws java.lang.Exception on any error an <CODE>java.lang.Exception</CODE> was thrown + * @return calc sheet + * @see com.sun.star.sheet.XSpreadsheet + */ + private static XSpreadsheet getSpreadSheetFromSheetDoc(XComponent xSheetDoc, int sheetNumber) + throws java.lang.Exception { + + XSpreadsheet xSheet = null; + + try{ + XSpreadsheetDocument xSpreadsheetDoc = UnoRuntime.queryInterface(XSpreadsheetDocument.class, xSheetDoc); + + XSpreadsheets xSpreadsheets = xSpreadsheetDoc.getSheets(); + + XIndexAccess xSheetsIndexArray = UnoRuntime.queryInterface(XIndexAccess.class, xSpreadsheets); + + xSheet = (XSpreadsheet) AnyConverter.toObject( + new Type(XSpreadsheet.class),xSheetsIndexArray.getByIndex(sheetNumber)); + + } catch (IllegalArgumentException ex){ + throw new Exception(ex, "Couldn't get sheet '" +sheetNumber + "'"); + } catch (IndexOutOfBoundsException ex){ + throw new Exception(ex, "Couldn't get sheet '" +sheetNumber + "'"); + } catch (WrappedTargetException ex) { + throw new Exception(ex, "Couldn't get sheet '" +sheetNumber + "'"); + } + return xSheet; + } +} diff --git a/qadevOOo/runner/util/DBTools.java b/qadevOOo/runner/util/DBTools.java new file mode 100644 index 000000000..387ba57e8 --- /dev/null +++ b/qadevOOo/runner/util/DBTools.java @@ -0,0 +1,409 @@ +/* + * 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 util; + +import com.sun.star.uno.Exception; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.uno.UnoRuntime; + +import com.sun.star.beans.PropertyValue; +import com.sun.star.beans.XPropertySet; +import com.sun.star.sdbc.XConnection ; +import com.sun.star.util.Date ; +import com.sun.star.uno.XNamingService ; +import com.sun.star.task.XInteractionHandler ; +import com.sun.star.sdb.XCompletedConnection ; +import com.sun.star.frame.XStorable; +import com.sun.star.sdb.XDocumentDataSource; +import java.sql.Statement; +import java.sql.Connection; +import java.sql.DriverManager; + +/** +* Provides useful methods for working with SOffice databases. +* Database creation, data transferring, outputting information. +*/ +public class DBTools { + + private final XMultiServiceFactory xMSF; + private XNamingService dbContext; + //JDBC driver + public static final String TST_JDBC_DRIVER = "org.gjt.mm.mysql.Driver"; + + // constants for TestDB table column indexes + public static final int TST_STRING = 1 ; + public static final int TST_INT = 2 ; + private static final int TST_DOUBLE = 5 ; + private static final int TST_DATE = 6 ; + private static final int TST_BOOLEAN = 10 ; + private static final int TST_CHARACTER_STREAM = 11 ; + private static final int TST_BINARY_STREAM = 12 ; + + // constants for TestDB columns names + public static final String TST_STRING_F = "_TEXT" ; + public static final String TST_INT_F = "_INT" ; + public static final String TST_DOUBLE_F = "_DOUBLE" ; + public static final String TST_DATE_F = "_DATE" ; + private static final String TST_BOOLEAN_F = "_BOOL" ; + private static final String TST_CHARACTER_STREAM_F = "_MEMO1" ; + public static final String TST_BINARY_STREAM_F = "_MEMO2" ; + + /** + * Values for filling test table. + */ + public static final Object[][] TST_TABLE_VALUES = new Object[][] { + {"String1", Integer.valueOf(1), null, null, new Double(1.1), + new Date((short) 1,(short) 1, (short) 2001), null, null, null, + Boolean.TRUE, null, null}, + {"String2", Integer.valueOf(2), null, null, new Double(1.2), + new Date((short) 2, (short) 1,(short) 2001), null, null, null, + Boolean.FALSE, null, null}, + {null, null, null, null, null, + null, null, null, null, + null, null, null} + } ; + + /** + * It's just a structure with some useful methods for representing + * <code>com.sun.star.sdb.DataSource</code> service. All this + * service's properties are stored in appropriate class fields. + * Class also allows to construct its instances using service + * information, and create new service instance upon class + * fields. + * @see com.sun.star.sdb.DataSource + */ + public class DataSourceInfo { + /** + * Representation of <code>'Name'</code> property. + */ + public String Name = null ; + /** + * Representation of <code>'URL'</code> property. + */ + public String URL = null ; + /** + * Representation of <code>'Info'</code> property. + */ + public PropertyValue[] Info = null ; + /** + * Representation of <code>'User'</code> property. + */ + public String User = null ; + /** + * Representation of <code>'Password'</code> property. + */ + public String Password = null ; + /** + * Representation of <code>'IsPasswordRequired'</code> property. + */ + public Boolean IsPasswordRequired = null ; + + /** + * Creates new <code>com.sun.star.sdb.DataSource</code> service + * instance and copies all fields (which are not null) to + * appropriate service properties. + * @return <code>com.sun.star.sdb.DataSource</code> service. + */ + public Object getDataSourceService() throws Exception + { + Object src = xMSF.createInstance("com.sun.star.sdb.DataSource") ; + + XPropertySet props = UnoRuntime.queryInterface + (XPropertySet.class, src) ; + + if (Name != null) props.setPropertyValue("Name", Name) ; + if (URL != null) props.setPropertyValue("URL", URL) ; + if (Info != null) props.setPropertyValue("Info", Info) ; + if (User != null) props.setPropertyValue("User", User) ; + if (Password != null) props.setPropertyValue("Password", Password) ; + if (IsPasswordRequired != null) props.setPropertyValue("IsPasswordRequired", IsPasswordRequired) ; + return src ; + } + } + + /** + * Creates class instance. + * @param xMSF <code>XMultiServiceFactory</code>. + */ + public DBTools(XMultiServiceFactory xMSF ) + { + this.xMSF = xMSF ; + try { + Object cont = xMSF.createInstance("com.sun.star.sdb.DatabaseContext") ; + + dbContext = UnoRuntime.queryInterface + (XNamingService.class, cont) ; + + } catch (com.sun.star.uno.Exception e) { + System.out.println("caught exception: " + e); + } + } + + /** + * Returns new instance of <code>DataSourceInfo</code> class. + */ + public DataSourceInfo newDataSourceInfo() { return new DataSourceInfo() ;} + + + + /** + * Registers the datasource on the specified name in + * <code>DatabaseContext</code> service. + * @param name Name which dataSource will have in global context. + * @param dataSource <code>DataSource</code> object which is to + * be registered. + */ + private void registerDB(String name, Object dataSource) + throws com.sun.star.uno.Exception { + + dbContext.registerObject(name, dataSource) ; + } + + + /** + * First tries to revoke the datasource with the specified + * name and then registers a new one. + * @param name Name which dataSource will have in global context. + * @param dataSource <code>DataSource</code> object which is to + * be registered. + */ + public void reRegisterDB(String name, Object dataSource) + throws com.sun.star.uno.Exception { + + try { + revokeDB(name) ; + } catch (com.sun.star.uno.Exception e) {} + + XDocumentDataSource xDDS = UnoRuntime.queryInterface(XDocumentDataSource.class, dataSource); + XStorable store = UnoRuntime.queryInterface(XStorable.class, + xDDS.getDatabaseDocument()); + String aFile = utils.getOfficeTemp(xMSF) + name + ".odb"; + store.storeAsURL(aFile, new PropertyValue[] { }); + + registerDB(name, dataSource) ; + } + + + + + + /** + * Performs connection to DataSource specified. + * @param dbSource <code>com.sun.star.sdb.DataSource</code> service + * specified data source which must be already registered in the + * <code>DatabaseContext</code> service. + * @return Connection to the data source. + */ + public XConnection connectToSource(Object dbSource) + throws com.sun.star.uno.Exception { + + Object handler = xMSF.createInstance("com.sun.star.sdb.InteractionHandler"); + XInteractionHandler xHandler = UnoRuntime.queryInterface(XInteractionHandler.class, handler) ; + + XCompletedConnection xSrcCon = UnoRuntime.queryInterface(XCompletedConnection.class, dbSource) ; + + return xSrcCon.connectWithCompletion(xHandler) ; + } + + /** + * Convert system pathname to SOffice URL string + * (for example 'C:\Temp\DBDir\' -> 'file:///C|/Temp/DBDir/'). + * (for example '\\server\Temp\DBDir\' -> 'file://server/Temp/DBDir/'). + * Already converted string returned unchanged. + */ + public static String dirToUrl(String dir) { + String retVal = null; + if (dir.startsWith("file:/")) retVal = dir; + else { + retVal = dir.replace(':', '|').replace('\\', '/'); + + if (dir.startsWith("\\\\")) { + retVal = "file:" + retVal; + } + + else retVal = "file:///" + retVal ; + } + return retVal; + } + + /** + * Revokes datasource from global DB context. + * @param name DataSource name to be revoked. + */ + public void revokeDB(String name) throws com.sun.star.uno.Exception + { + dbContext.revokeObject(name) ; + } + + /** + * Initializes test table specified of the connection specified + * using JDBC driver. Drops table with the name <code>tbl_name</code>, + * creates new table with this name and then inserts data from + * <code>TST_TABLE_VALUES</code> constant array. <p> + * Test table has some predefined format which includes as much + * field types as possible. For every column type constants + * {@link #TST_STRING TST_STRING}, {@link #TST_INT TST_INT}, etc. + * are declared for column index fast find. + * @param tbl_name Test table name. + */ + public void initTestTableUsingJDBC(String tbl_name, DataSourceInfo dsi) + throws java.sql.SQLException, + ClassNotFoundException { + + //register jdbc driver + if ( dsi.Info[0].Name.equals("JavaDriverClass") ) { + Class.forName((String)dsi.Info[0].Value); + } else { + Class.forName(TST_JDBC_DRIVER); + } + + Connection connection = null; + Statement statement = null; + try { + //getting connection + connection = DriverManager.getConnection(dsi.URL, dsi.User, dsi.Password); + try { + statement = connection.createStatement(); + + //drop table + dropMySQLTable(statement, tbl_name); + + //create table + createMySQLTable(statement, tbl_name); + + //insert some content + insertContentMySQLTable(statement, tbl_name); + } finally { + if (statement != null) + statement.close(); + } + } finally { + if (connection != null) + connection.close(); + } + } + + /** + * Inserts data from <code>TST_TABLE_VALUES</code> constant array + * to test table <code>tbl_name</code>. + * @param statement object used for executing a static SQL + * statement and obtaining the results produced by it. + * @param tbl_name Test table name. + */ + private void insertContentMySQLTable(Statement statement, String tbl_name) + throws java.sql.SQLException { + + + for(int i = 0; i < DBTools.TST_TABLE_VALUES.length; i++) { + StringBuilder query = new StringBuilder("insert into " + tbl_name + " values ("); + int j = 0; + while(j < DBTools.TST_TABLE_VALUES[i].length) { + if (j > 0) { + query.append(", "); + } + Object value = DBTools.TST_TABLE_VALUES[i][j]; + if (value instanceof String || + value instanceof Date) { + query.append("'"); + } + if (value instanceof Date) { + Date date = (Date)value; + query.append(date.Year).append("-").append(date.Month).append( + "-").append(date.Day); + } else if (value instanceof Boolean) { + query.append((((Boolean)value).booleanValue()) + ? "1" : "0"); + } else { + query.append(value); + } + + if (value instanceof String || + value instanceof Date) { + query.append("'"); + } + j++; + } + query.append(")"); + statement.executeUpdate(query.toString()); + } + } + + /** + * Creates test table specified. + * Test table has some predefined format which includes as much + * field types as possible. For every column type constants + * {@link #TST_STRING TST_STRING}, {@link #TST_INT TST_INT}, etc. + * are declared for column index fast find. + * @param statement object used for executing a static SQL + * statement and obtaining the results produced by it. + * @param tbl_name Test table name. + */ + private void createMySQLTable(Statement statement, String tbl_name) + throws java.sql.SQLException { + + final String empty_col_name = "Column"; + int c = 0; + String query = "create table " + tbl_name + " ("; + for (int i = 0; i < TST_TABLE_VALUES[0].length; i++) { + if (i > 0) query += ","; + + switch(i + 1) { + case TST_BINARY_STREAM: + query += TST_BINARY_STREAM_F + " BLOB"; + break; + case TST_BOOLEAN: + query += TST_BOOLEAN_F + " TINYINT"; + break; + case TST_CHARACTER_STREAM: + query += TST_CHARACTER_STREAM_F + " TEXT"; + break; + case TST_DATE: + query += TST_DATE_F + " DATE"; + break; + case TST_DOUBLE: + query += TST_DOUBLE_F + " DOUBLE"; + break; + case TST_INT: + query += TST_INT_F + " INT"; + break; + case TST_STRING: + query += TST_STRING_F + " TEXT"; + break; + default: query += empty_col_name + (c++) + " INT"; + if (c == 1) { + query += " NOT NULL AUTO_INCREMENT"; + } + } + } + query += ", PRIMARY KEY (" + empty_col_name + "0)"; + query += ")"; + statement.execute(query); + } + + /** + * Drops table. + * @param statement object used for executing a static SQL + * statement and obtaining the results produced by it. + * @param tbl_name Test table name. + */ + private void dropMySQLTable(Statement statement, String tbl_name) + throws java.sql.SQLException { + statement.executeUpdate("drop table if exists " + tbl_name); + } +} diff --git a/qadevOOo/runner/util/DefaultDsc.java b/qadevOOo/runner/util/DefaultDsc.java new file mode 100644 index 000000000..9c270007c --- /dev/null +++ b/qadevOOo/runner/util/DefaultDsc.java @@ -0,0 +1,75 @@ +/* + * 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 util; + +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.uno.XInterface; +import com.sun.star.uno.UnoRuntime; + +/** + * This descriptor is useful for instances in default values. + */ +public class DefaultDsc extends InstDescr { + + private final String name = null; + private final String ifcName; + private final String service; + + public DefaultDsc( String Interface, String kind ) { + service = kind; + ifcName = Interface; + initDefault(); + } + @Override + public String getName() { + return name; + } + + @Override + public String getIfcName() { + return ifcName; + } + @Override + public String getService() { + return service; + } + + private void initDefault() { + try { + ifcClass = Class.forName( ifcName ); + } + catch( ClassNotFoundException cnfE ) { + } + } + @Override + public XInterface createInstance( XMultiServiceFactory docMSF ) { + + Object SrvObj = null; + try { + SrvObj = docMSF.createInstance( service ); + } + catch( com.sun.star.uno.Exception cssuE ){ + } + + XInterface Default = (XInterface)UnoRuntime.queryInterface(ifcClass, SrvObj ); + + return Default; + + } +} diff --git a/qadevOOo/runner/util/DesktopTools.java b/qadevOOo/runner/util/DesktopTools.java new file mode 100644 index 000000000..1c1b04402 --- /dev/null +++ b/qadevOOo/runner/util/DesktopTools.java @@ -0,0 +1,516 @@ +/* + * 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 util; + +import helper.ConfigHelper; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.InputStream; +import java.util.ArrayList; + +import lib.StatusException; + +import com.sun.star.awt.Rectangle; +import com.sun.star.awt.WindowDescriptor; +import com.sun.star.awt.XToolkit; +import com.sun.star.awt.XTopWindow; +import com.sun.star.awt.XWindowPeer; +import com.sun.star.beans.PropertyValue; +import com.sun.star.beans.XPropertySet; +import com.sun.star.container.XEnumeration; +import com.sun.star.frame.XComponentLoader; +import com.sun.star.frame.XDesktop; +import com.sun.star.frame.XFrame; +import com.sun.star.frame.XModel; +import com.sun.star.io.XInputStream; +import com.sun.star.lang.XComponent; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.lib.uno.adapter.ByteArrayToXInputStreamAdapter; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XInterface; +import com.sun.star.util.XCloseable; +import com.sun.star.util.XModifiable; +import com.sun.star.view.XViewSettingsSupplier; + +/** + * contains helper methods for the Desktop + */ +public class DesktopTools +{ + + /** + * Queries the XComponentLoader + * + * @param xMSF the MultiServiceFactory + * @return the gained XComponentLoader + */ + private static XComponentLoader getCLoader(XMultiServiceFactory xMSF) + { + XComponentLoader oCLoader = UnoRuntime.queryInterface( + XComponentLoader.class, createDesktop(xMSF)); + + return oCLoader; + } + + /** + * Creates an Instance of the Desktop service + * + * @param xMSF the MultiServiceFactory + * @return the gained XDesktop object + */ + public static XDesktop createDesktop(XMultiServiceFactory xMSF) + { + XDesktop xDesktop; + + try + { + xDesktop = UnoRuntime.queryInterface( + XDesktop.class, xMSF.createInstance("com.sun.star.comp.framework.Desktop")); + } + catch (com.sun.star.uno.Exception e) + { + throw new IllegalArgumentException("Desktop Service not available", e); + } + + return xDesktop; + } + + /** + * returns a XEnumeration containing all components containing on the desktop + * @param xMSF the XMultiServiceFactory + * @return XEnumeration of all components on the desktop + */ + public static XEnumeration getAllComponents(XMultiServiceFactory xMSF) + { + return createDesktop(xMSF).getComponents().createEnumeration(); + } + + + + /** + * returns the current component on the desktop + * @param xMSF the XMultiServiceFactory + * @return XComponent of the current component on the desktop + */ + public static XFrame getCurrentFrame(XMultiServiceFactory xMSF) + { + return createDesktop(xMSF).getCurrentFrame(); + } + + /** + * returns an object array of all open documents + * @param xMSF the MultiServiceFactory + * @return returns an Array of document kinds like ["swriter"] + */ + public static Object[] getAllOpenDocuments(XMultiServiceFactory xMSF) + { + ArrayList<XComponent> components = new ArrayList<XComponent>(); + + XEnumeration allComp = getAllComponents(xMSF); + + while (allComp.hasMoreElements()) + { + try + { + XComponent xComponent = UnoRuntime.queryInterface( + XComponent.class, allComp.nextElement()); + + if (getDocumentType(xComponent) != null) + { + components.add(xComponent); + } + + } + catch (com.sun.star.container.NoSuchElementException e) + { + } + catch (com.sun.star.lang.WrappedTargetException e) + { + } + } + return components.toArray(); + } + + /** + * Returns the document type for the given XComponent of a document + * @param xComponent the document to query for its type + * @return possible: + * <ul> + * <li>swriter</li> + * <li>scalc</li> + * <li>sdraw</li> + * <li>smath</li> + * </ul> + * or <CODE>null</CODE> + */ + private static String getDocumentType(XComponent xComponent) + { + XServiceInfo sInfo = UnoRuntime.queryInterface( + XServiceInfo.class, xComponent); + + if (sInfo == null) + { + return ""; + } + else if (sInfo.supportsService("com.sun.star.sheet.SpreadsheetDocument")) + { + return "scalc"; + } + else if (sInfo.supportsService("com.sun.star.text.TextDocument")) + { + return "swriter"; + } + else if (sInfo.supportsService("com.sun.star.drawing.DrawingDocument")) + { + return "sdraw"; + } + else if (sInfo.supportsService("com.sun.star.presentation.PresentationDocument")) + { + return "simpress"; + } + else if (sInfo.supportsService("com.sun.star.formula.FormulaProperties")) + { + return "smath"; + } + else + { + return null; + } + } + + /** + * Opens a new document of a given kind + * with arguments + * @return the XComponent Interface of the document + * @param kind the kind of document to load.<br> + * possible: + * <ul> + * <li>swriter</li> + * <li>scalc</li> + * <li>sdaw</li> + * <li>smath</li> + * </ul> + * @param Args arguments which passed to the document to load + * @param xMSF the MultiServiceFactory + */ + public static XComponent openNewDoc(XMultiServiceFactory xMSF, String kind, + PropertyValue[] Args) + { + XComponent oDoc = null; + + try + { + oDoc = getCLoader(xMSF).loadComponentFromURL("private:factory/" + kind, + "_blank", 0, Args); + } + catch (com.sun.star.uno.Exception e) + { + throw new IllegalArgumentException("Document could not be opened", e); + } + + return oDoc; + } + + /** + * loads a document of from a given url + * with arguments + * @return the XComponent Interface of the document + * @param url the URL of the document to load. + * @param Args arguments which passed to the document to load + * @param xMSF the MultiServiceFactory + */ + public static XComponent loadDoc(XMultiServiceFactory xMSF, String url, + PropertyValue[] Args) + { + XComponent oDoc = null; + if (Args == null) + { + Args = new PropertyValue[0]; + } + try + { + oDoc = getCLoader(xMSF).loadComponentFromURL(url, "_blank", 0, Args); + } + catch (com.sun.star.uno.Exception e) + { + throw new IllegalArgumentException("Document could not be loaded", e); + } + + bringWindowToFront(oDoc); + return oDoc; + } + + /** + * loads a document of from a given path using an input stream + * + * @param xMSF the MultiServiceFactory + * @param filePath the path of the document to load. + * @return the XComponent Interface of the document + */ + public static XComponent loadDocUsingStream(XMultiServiceFactory xMSF, String filePath) + { + XInputStream inputStream = null; + try { + final InputStream inputFile = new BufferedInputStream( + new FileInputStream(filePath)); + try { + final ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + final byte[] byteBuffer = new byte[4096]; + int byteBufferLength = 0; + while ((byteBufferLength = inputFile.read(byteBuffer)) > 0) + bytes.write(byteBuffer, 0, byteBufferLength); + inputStream = new ByteArrayToXInputStreamAdapter( + bytes.toByteArray()); + } finally { + inputFile.close(); + } + } catch (java.io.IOException e) { + e.printStackTrace(); + } + + PropertyValue[] loadProps = new PropertyValue[1]; + loadProps[0] = new PropertyValue(); + loadProps[0].Name = "InputStream"; + loadProps[0].Value = inputStream; + + XComponent oDoc = null; + try + { + oDoc = getCLoader(xMSF).loadComponentFromURL("private:stream", "_blank", 0, loadProps); + } + catch (com.sun.star.uno.Exception e) + { + throw new IllegalArgumentException("Document could not be loaded", e); + } + return oDoc; + } + + /** + * closes a given document + * @param DocumentToClose the document to close + */ + public static void closeDoc(XInterface DocumentToClose) + { + if (DocumentToClose == null) + { + return; + } + + String kd = System.getProperty("KeepDocument"); + if (kd != null) + { + System.out.println("The property 'KeepDocument' is set and so the document won't be disposed"); + return; + } + XModifiable modified = UnoRuntime.queryInterface(XModifiable.class, DocumentToClose); + XCloseable closer = UnoRuntime.queryInterface(XCloseable.class, DocumentToClose); + + try + { + if (modified != null) + { + modified.setModified(false); + } + closer.close(true); + } + catch (com.sun.star.util.CloseVetoException e) + { + System.out.println("Couldn't close document"); + } + catch (com.sun.star.lang.DisposedException e) + { + System.out.println("Couldn't close document"); + } + catch (NullPointerException e) + { + System.out.println("Couldn't close document"); + } + catch (com.sun.star.beans.PropertyVetoException e) + { + System.out.println("Couldn't close document"); + } + } + + /** + * Creates a floating XWindow with the size of X=500 Y=100 width=400 height=600 + * @param xMSF the MultiServiceFactory + * @throws lib.StatusException if it is not possible to create a floating window a lib.StatusException was thrown + * @return a floating XWindow + */ + public static XWindowPeer createFloatingWindow(XMultiServiceFactory xMSF) + throws StatusException + { + return createFloatingWindow(xMSF, 500, 100, 400, 600); + } + + /** + * Creates a floating XWindow on the given position and size. + * @return a floating XWindow + * @param X the X-Position of the floating XWindow + * @param Y the Y-Position of the floating XWindow + * @param width the width of the floating XWindow + * @param height the height of the floating XWindow + * @param xMSF the MultiServiceFactory + * @throws lib.StatusException if it is not possible to create a floating window a lib.StatusException was thrown + */ + public static XWindowPeer createFloatingWindow(XMultiServiceFactory xMSF, int X, int Y, int width, int height) + throws StatusException + { + + XInterface oObj = null; + + try + { + oObj = (XInterface) xMSF.createInstance("com.sun.star.awt.Toolkit"); + } + catch (com.sun.star.uno.Exception e) + { + throw new StatusException("Couldn't get toolkit", e); + } + + XToolkit tk = UnoRuntime.queryInterface( + XToolkit.class, oObj); + + WindowDescriptor descriptor = new com.sun.star.awt.WindowDescriptor(); + + descriptor.Type = com.sun.star.awt.WindowClass.TOP; + descriptor.WindowServiceName = "modelessdialog"; + descriptor.ParentIndex = -1; + + Rectangle bounds = new com.sun.star.awt.Rectangle(); + bounds.X = X; + bounds.Y = Y; + bounds.Width = width; + bounds.Height = height; + + descriptor.Bounds = bounds; + descriptor.WindowAttributes = (com.sun.star.awt.WindowAttribute.BORDER + + com.sun.star.awt.WindowAttribute.MOVEABLE + + com.sun.star.awt.WindowAttribute.SIZEABLE + + com.sun.star.awt.WindowAttribute.CLOSEABLE + + com.sun.star.awt.VclWindowPeerAttribute.CLIPCHILDREN); + + XWindowPeer xWindow = null; + + try + { + xWindow = tk.createWindow(descriptor); + } + catch (com.sun.star.lang.IllegalArgumentException e) + { + throw new StatusException("Could not create window", e); + } + + return xWindow; + + } + + /** + * zoom to have a view over the whole page + * @param xDoc the document to zoom + */ + public static void zoomToEntirePage(XMultiServiceFactory xMSF, XInterface xDoc) + { + try + { + XModel xMod = UnoRuntime.queryInterface(XModel.class, xDoc); + XInterface oCont = xMod.getCurrentController(); + XViewSettingsSupplier oVSSupp = UnoRuntime.queryInterface(XViewSettingsSupplier.class, oCont); + + XInterface oViewSettings = oVSSupp.getViewSettings(); + XPropertySet oViewProp = UnoRuntime.queryInterface(XPropertySet.class, oViewSettings); + oViewProp.setPropertyValue("ZoomType", + Short.valueOf(com.sun.star.view.DocumentZoomType.ENTIRE_PAGE)); + + util.utils.waitForEventIdle(xMSF); + } + catch (Exception e) + { + System.out.println("Could not zoom to entire page: " + e.toString()); + } + + } + + /** + * This function docks the Navigator onto the right side of the window.</p> + * Note:<P> + * Since the svt.viewoptions cache the view configuration at start up + * the change of the docking will be effective at a restart. + * @param xMSF the XMultiServiceFactory + */ + public static void dockNavigator(XMultiServiceFactory xMSF) + { + // prepare Window settings + try + { + ConfigHelper aConfig = new ConfigHelper(xMSF, + "org.openoffice.Office.Views", false); + + aConfig.getOrInsertGroup("Windows", "10366"); + + aConfig.updateGroupProperty( + "Windows", "10366", "WindowState", "952,180,244,349;1;0,0,0,0;"); + + aConfig.insertOrUpdateExtensibleGroupProperty( + "Windows", "10366", "UserData", "Data", "V2,V,0,AL:(5,16,0/0/244/349,244;610)"); + + // Is node "SplitWindow2" available? If not, insert it. + aConfig.getOrInsertGroup("Windows", "SplitWindow2"); + + aConfig.insertOrUpdateExtensibleGroupProperty( + "Windows", "SplitWindow2", "UserData", "UserItem", "V1,2,1,0,10366"); + + aConfig.flush(); + aConfig = null; + + } + catch (com.sun.star.uno.Exception e) + { + e.printStackTrace(); + } + } + + + /** + * This function brings a document to the front.<P> + * NOTE: it is not possible to change the window order of your Window-Manager!! + * Only the order of Office documents are changeable. + * @param xModel the XModel of the document to bring to top + */ + public static void bringWindowToFront(XModel xModel) + { + XTopWindow xTopWindow = + UnoRuntime.queryInterface( + XTopWindow.class, + xModel.getCurrentController().getFrame().getContainerWindow()); + + xTopWindow.toFront(); + } + + public static void bringWindowToFront(XComponent xComponent) + { + XModel xModel = UnoRuntime.queryInterface(XModel.class, xComponent); + if (xModel != null) + { + bringWindowToFront(xModel); + } + } +} diff --git a/qadevOOo/runner/util/DrawTools.java b/qadevOOo/runner/util/DrawTools.java new file mode 100644 index 000000000..a8f416312 --- /dev/null +++ b/qadevOOo/runner/util/DrawTools.java @@ -0,0 +1,103 @@ +/* + * 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 util; + +// access the implementations via names +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.uno.UnoRuntime; + +import com.sun.star.beans.PropertyValue; +import com.sun.star.lang.XComponent; +import com.sun.star.drawing.XDrawPages; +import com.sun.star.drawing.XDrawPagesSupplier; +import com.sun.star.drawing.XDrawPage; +import com.sun.star.drawing.XShapes; +import com.sun.star.uno.AnyConverter; +import com.sun.star.uno.Type; + +/** + * contains helper methods for draw documents + */ + + +public class DrawTools { + + /** + * Opens a new draw document + * with arguments + * @param xMSF the MultiServiceFactory + * @return the XComponent Interface of the document + */ + + public static XComponent createDrawDoc( XMultiServiceFactory xMSF ) { + PropertyValue[] Args = new PropertyValue [0]; + XComponent DrawDoc = DesktopTools.openNewDoc( xMSF, "sdraw", Args ); + return DrawDoc; + } // finish createDrawDoc + + /** + * gets the XDrawPages container of a draw document + * + * @param aDoc the draw document + * @return the XDrawpages container of the document + */ + + public static XDrawPages getDrawPages ( XComponent aDoc ) { + XDrawPages oDPn = null; + try { + XDrawPagesSupplier oDPS = UnoRuntime.queryInterface(XDrawPagesSupplier.class,aDoc); + + oDPn = oDPS.getDrawPages(); + } catch ( Exception e ) { + throw new IllegalArgumentException( "Couldn't get drawpages", e ); + } + return oDPn; + } // finish getDrawPages + + /** + * gets the specified XDrawPage of a draw document + * + * @param aDoc the draw document + * @param nr the index of the DrawPage + * @return the XDrawpage with index nr of the document + */ + + public static XDrawPage getDrawPage ( XComponent aDoc, int nr ) { + XDrawPage oDP = null; + try { + oDP = (XDrawPage) AnyConverter.toObject( + new Type(XDrawPage.class),getDrawPages( aDoc ).getByIndex( nr )); + } catch ( Exception e ) { + throw new IllegalArgumentException( "Couldn't get drawpage", e ); + } + return oDP; + } + + /** + * gets the XShapes container of a draw page + * + * @param oDP the draw page + * @return the XDrawShape container of the drawpage + */ + + public static XShapes getShapes ( XDrawPage oDP ) { + return UnoRuntime.queryInterface(XShapes.class,oDP); + } + +} diff --git a/qadevOOo/runner/util/DynamicClassLoader.java b/qadevOOo/runner/util/DynamicClassLoader.java new file mode 100644 index 000000000..e2bab1f9d --- /dev/null +++ b/qadevOOo/runner/util/DynamicClassLoader.java @@ -0,0 +1,97 @@ +/* + * 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 util; + +import java.lang.reflect.Constructor; + +public class DynamicClassLoader { + + /** + * This method returns a class created by its name + * created by call to <code>Class.forName()</code>.<p> + * This method must be overridden if another loading + * policy is required for Component and Interface + * testing classes. + * @param className The name of the class to create. + * @return The created class. + */ + private static Class<?> forName(String className) + throws ClassNotFoundException { + + return Class.forName(className) ; + } + + /** + * Get an instance of a class. The empty constructor is used. + * @param className The class to instantiate. + * @return The instance of the class. + */ + public Object getInstance(String className) + throws IllegalArgumentException { + try { + Class<?> cls = DynamicClassLoader.forName(className); + return cls.newInstance(); + } catch ( ClassNotFoundException e ) { + throw new IllegalArgumentException("Couldn't find " + className + + " " + e); + } catch ( IllegalAccessException e ) { + throw new IllegalArgumentException("Couldn't access " + className + + " " + e); + } catch ( InstantiationException e ) { + throw new IllegalArgumentException("Couldn't instantiate " + + className + " " + e); + } + } + + /** + * Get an instance of a class. The constructor matching to the + * given calls types is used and the instance is created using the arguments + * for the constructor. + * @param className The class to instantiate. + * @param ctorClassTypes The class types matching to the constructor. + * @param ctorArgs Arguments for the constructor. + * @return The instance of the class. + */ + public Object getInstance(String className, Class<?>[]ctorClassTypes, Object[] ctorArgs) + throws IllegalArgumentException { + try { + Class<?> cls = DynamicClassLoader.forName(className); + Constructor<?> ctor = cls.getConstructor(ctorClassTypes); + System.out.println("ctor: " + ctor.getName() + " " + ctor.getModifiers()); + + return ctor.newInstance(ctorArgs); + } catch ( ClassNotFoundException e ) { + throw new IllegalArgumentException("Couldn't find " + className + + " " + e); + } catch ( IllegalAccessException e ) { + throw new IllegalArgumentException("Couldn't access " + className + + " " + e); + } catch ( NoSuchMethodException e ) { + throw new IllegalArgumentException("Couldn't find constructor for " + className + + " " + e); + } catch ( java.lang.reflect.InvocationTargetException e ) { + e.printStackTrace(); + throw new IllegalArgumentException("Couldn't invoke " + + className + " " + e); + } catch ( InstantiationException e ) { + throw new IllegalArgumentException("Couldn't instantiate " + + className + " " + e); + } + } +} diff --git a/qadevOOo/runner/util/FootnoteDsc.java b/qadevOOo/runner/util/FootnoteDsc.java new file mode 100644 index 000000000..b14f70bf8 --- /dev/null +++ b/qadevOOo/runner/util/FootnoteDsc.java @@ -0,0 +1,72 @@ +/* + * 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 util; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.uno.XInterface; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.text.XTextContent; + +/** + * describes a Footnote to be inserted in a container + */ +public class FootnoteDsc extends InstDescr { + + private static final String service = "com.sun.star.text.Footnote"; + private static final String ifcName = "com.sun.star.text.XTextContent"; + + public FootnoteDsc() { + initFootnote(); + } + + @Override + public String getName() { + return null; + } + + @Override + public String getIfcName() { + return ifcName; + } + + @Override + public String getService() { + return service; + } + + private void initFootnote() { + try { + ifcClass = Class.forName( ifcName ); + } + catch( ClassNotFoundException cnfE ) { + } + } + @Override + public XInterface createInstance( XMultiServiceFactory docMSF ) { + Object ServiceObj = null; + + try { + ServiceObj = docMSF.createInstance( service ); + } + catch( com.sun.star.uno.Exception cssuE ){ + } + XTextContent FN = (XTextContent)UnoRuntime.queryInterface( ifcClass, + ServiceObj ); + return FN; + } +} diff --git a/qadevOOo/runner/util/FormTools.java b/qadevOOo/runner/util/FormTools.java new file mode 100644 index 000000000..2189612cd --- /dev/null +++ b/qadevOOo/runner/util/FormTools.java @@ -0,0 +1,287 @@ +/* + * 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 util; + +// access the implementations via names +import com.sun.star.uno.XInterface; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.lang.XComponent; +import com.sun.star.drawing.XControlShape; +import com.sun.star.drawing.XDrawPage; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.awt.Size; +import com.sun.star.awt.Point; +import com.sun.star.awt.XControlModel; +import com.sun.star.container.XNameContainer; +import com.sun.star.container.XIndexContainer; +import com.sun.star.form.XFormsSupplier; +import com.sun.star.form.XForm; +import com.sun.star.form.XLoadable; +import com.sun.star.text.XTextDocument; +import com.sun.star.beans.XPropertySet; +import com.sun.star.uno.AnyConverter; +import com.sun.star.uno.Type; + +/** + * contains helper methods forms + */ + +public class FormTools { + + + /** + * creates a XControlShape + * + * @param oDoc the document + * @param height the height of the shape + * @param width the width of the shape + * @param x the x-position of the shape + * @param y the y-position of the shape + * @param kind the kind of the shape + * @return the created XControlShape + */ + public static XControlShape createControlShape( XComponent oDoc, int height, + int width, int x, int y, String kind ) + throws com.sun.star.uno.Exception + { + + Size size = new Size(); + Point position = new Point(); + XControlShape oCShape = null; + XControlModel aControl = null; + + XMultiServiceFactory oDocMSF = UnoRuntime.queryInterface( XMultiServiceFactory.class, oDoc ); + + Object oInt = oDocMSF.createInstance("com.sun.star.drawing.ControlShape"); + Object aCon = oDocMSF.createInstance("com.sun.star.form.component."+kind); + XPropertySet model_props = UnoRuntime.queryInterface(XPropertySet.class,aCon); + model_props.setPropertyValue("DefaultControl","com.sun.star.form.control."+kind); + aControl = UnoRuntime.queryInterface( XControlModel.class, aCon ); + oCShape = UnoRuntime.queryInterface( XControlShape.class, oInt ); + size.Height = height; + size.Width = width; + position.X = x; + position.Y = y; + oCShape.setSize(size); + oCShape.setPosition(position); + + oCShape.setControl(aControl); + + return oCShape; + } // finish createControlShape + + public static XControlShape createUnoControlShape( XComponent oDoc, int height, + int width, int x, int y, String kind, String defControl ) + throws com.sun.star.uno.Exception + { + + Size size = new Size(); + Point position = new Point(); + XControlShape oCShape = null; + XControlModel aControl = null; + + XMultiServiceFactory oDocMSF = UnoRuntime.queryInterface( XMultiServiceFactory.class, oDoc ); + + Object oInt = oDocMSF.createInstance("com.sun.star.drawing.ControlShape"); + Object aCon = oDocMSF.createInstance("com.sun.star.form.component."+kind); + XPropertySet model_props = UnoRuntime.queryInterface(XPropertySet.class,aCon); + model_props.setPropertyValue("DefaultControl","com.sun.star.awt."+defControl); + aControl = UnoRuntime.queryInterface( XControlModel.class, aCon ); + oCShape = UnoRuntime.queryInterface( XControlShape.class, oInt ); + size.Height = height; + size.Width = width; + position.X = x; + position.Y = y; + oCShape.setSize(size); + oCShape.setPosition(position); + + oCShape.setControl(aControl); + + return oCShape; + } // finish createControlShape + + public static XControlShape createControlShapeWithDefaultControl( XComponent oDoc, int height, + int width, int x, int y, String kind ) + throws com.sun.star.uno.Exception + { + + Size size = new Size(); + Point position = new Point(); + XControlShape oCShape = null; + XControlModel aControl = null; + + XMultiServiceFactory oDocMSF = UnoRuntime.queryInterface( XMultiServiceFactory.class, oDoc ); + + Object oInt = oDocMSF.createInstance("com.sun.star.drawing.ControlShape"); + Object aCon = oDocMSF.createInstance("com.sun.star.form.component."+kind); + + aControl = UnoRuntime.queryInterface( XControlModel.class, aCon ); + oCShape = UnoRuntime.queryInterface( XControlShape.class, oInt ); + size.Height = height; + size.Width = width; + position.X = x; + position.Y = y; + oCShape.setSize(size); + oCShape.setPosition(position); + + oCShape.setControl(aControl); + + return oCShape; + } // finish createControlShape + + public static XInterface createControl( XComponent oDoc, String kind ) + throws com.sun.star.uno.Exception + { + XInterface oControl = null; + + XMultiServiceFactory oDocMSF = UnoRuntime.queryInterface( XMultiServiceFactory.class, oDoc ); + + oControl = (XInterface) oDocMSF.createInstance( + "com.sun.star.form.component."+kind); + return oControl; + } // finish createControl + + public static XNameContainer getForms ( XDrawPage oDP ) + { + XFormsSupplier oFS = UnoRuntime.queryInterface( + XFormsSupplier.class,oDP); + return oFS.getForms(); + } //finish getForms + + private static XIndexContainer getIndexedForms ( XDrawPage oDP ) + { + XFormsSupplier oFS = UnoRuntime.queryInterface( + XFormsSupplier.class,oDP); + return UnoRuntime.queryInterface( XIndexContainer.class, + oFS.getForms() ); + } //finish getIndexedForms + + public static void insertForm ( XComponent aDoc, XNameContainer Forms, + String aName ) + throws com.sun.star.uno.Exception + { + XInterface oControl = createControl(aDoc, "Form"); + XForm oForm = UnoRuntime.queryInterface(XForm.class, oControl); + Forms.insertByName(aName,oForm); + } + + public static XControlShape insertControlShape( XComponent oDoc, int height, + int width, int x, int y, String kind ) + throws com.sun.star.uno.Exception + { + XControlShape aShape = createControlShape(oDoc,height,width,x,y,kind); + XDrawPage oDP = DrawTools.getDrawPage(oDoc,0); + DrawTools.getShapes(oDP).add(aShape); + return aShape; + } + + public static XLoadable bindForm( XTextDocument aDoc ) + throws com.sun.star.uno.Exception + { + XLoadable formLoader = null; + + Object aForm = FormTools.getIndexedForms(WriterTools.getDrawPage(aDoc)).getByIndex(0); + XForm the_form = null; + the_form = (XForm) AnyConverter.toObject(new Type(XForm.class), aForm); + XPropertySet formProps = UnoRuntime.queryInterface(XPropertySet.class, the_form); + formProps.setPropertyValue("DataSourceName","Bibliography"); + formProps.setPropertyValue("Command","biblio"); + formProps.setPropertyValue("CommandType",Integer.valueOf(com.sun.star.sdb.CommandType.TABLE)); + formLoader = UnoRuntime.queryInterface(XLoadable.class, the_form); + + return formLoader; + } + + /** + * Binds <code>'Standard'</code> form of <code>aDoc</code> Writer document + * to the <code>tableName</code> table of <code>sourceName</code> + * Data Source. + * @param aDoc Writer document where DB controls are added. + * @param sourceName The name of DataSource in the <code>DatabaseContext</code>. + * @param tableName The name of the table to which controls are bound. + * @return <code>com.sun.star.form.component.DatabaseForm</code> service + * implementation which is the bound form inside the document. + */ + public static XLoadable bindForm( XTextDocument aDoc, String sourceName, String tableName ) + throws com.sun.star.uno.Exception { + + XForm the_form = (XForm) AnyConverter.toObject(new Type(XForm.class), + FormTools.getIndexedForms(WriterTools.getDrawPage(aDoc)).getByIndex(0)); + XPropertySet formProps = UnoRuntime.queryInterface(XPropertySet.class, the_form); + formProps.setPropertyValue("DataSourceName",sourceName); + formProps.setPropertyValue("Command",tableName); + formProps.setPropertyValue("CommandType",Integer.valueOf(com.sun.star.sdb.CommandType.TABLE)); + + return UnoRuntime.queryInterface(XLoadable.class, the_form); + } + + + + /** + * Binds the form with the name specified of <code>aDoc</code> Writer document + * to the <code>tableName</code> table of <code>sourceName</code> + * Data Source. + * @param aDoc Writer document where DB controls are added. + * @param formName The name of the form to be bound. + * @param sourceName The name of DataSource in the <code>DatabaseContext</code>. + * @param tableName The name of the table to which controls are bound. + * @return <code>com.sun.star.form.component.DatabaseForm</code> service + * implementation which is the bound form inside the document. + */ + public static XLoadable bindForm( XTextDocument aDoc, String formName, String sourceName, + String tableName) throws com.sun.star.uno.Exception { + + XForm the_form = (XForm) AnyConverter.toObject(new Type(XForm.class), + FormTools.getForms(WriterTools.getDrawPage(aDoc)).getByName(formName)); + XPropertySet formProps = UnoRuntime.queryInterface(XPropertySet.class, the_form); + formProps.setPropertyValue("DataSourceName",sourceName); + formProps.setPropertyValue("Command",tableName); + formProps.setPropertyValue("CommandType",Integer.valueOf(com.sun.star.sdb.CommandType.TABLE)); + + return UnoRuntime.queryInterface(XLoadable.class, the_form); + } + + public static void switchDesignOf(XMultiServiceFactory xMSF, XTextDocument aDoc) + throws com.sun.star.uno.Exception + { + com.sun.star.frame.XController aController = aDoc.getCurrentController(); + com.sun.star.frame.XFrame aFrame = aController.getFrame(); + com.sun.star.frame.XDispatchProvider aDispProv = UnoRuntime.queryInterface(com.sun.star.frame.XDispatchProvider.class,aFrame); + com.sun.star.util.URL aURL = new com.sun.star.util.URL(); + aURL.Complete = ".uno:SwitchControlDesignMode"; + + Object instance = xMSF.createInstance("com.sun.star.util.URLTransformer"); + com.sun.star.util.XURLTransformer atrans = + UnoRuntime.queryInterface( + com.sun.star.util.XURLTransformer.class,instance); + com.sun.star.util.URL[] aURLA = new com.sun.star.util.URL[1]; + aURLA[0] = aURL; + atrans.parseStrict(aURLA); + aURL = aURLA[0]; + + com.sun.star.frame.XDispatch aDisp = aDispProv.queryDispatch(aURL, "", + com.sun.star.frame.FrameSearchFlag.SELF | + com.sun.star.frame.FrameSearchFlag.CHILDREN); + + com.sun.star.beans.PropertyValue[] noArgs = new com.sun.star.beans.PropertyValue[0]; + aDisp.dispatch(aURL, noArgs); + util.utils.waitForEventIdle(xMSF); // async dispatch + } + +} diff --git a/qadevOOo/runner/util/FrameDsc.java b/qadevOOo/runner/util/FrameDsc.java new file mode 100644 index 000000000..b2e690282 --- /dev/null +++ b/qadevOOo/runner/util/FrameDsc.java @@ -0,0 +1,109 @@ +/* + * 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 util; + +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.uno.XInterface; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.text.XTextFrame; +import com.sun.star.drawing.XShape; +import com.sun.star.awt.Size; +import com.sun.star.beans.XPropertySet; +/** + * the class FrameDsc + */ +public class FrameDsc extends InstDescr { + + private int height = 2000; + private int width = 2000; + private static final String ifcName = "com.sun.star.text.XTextFrame"; + private static final String service = "com.sun.star.text.TextFrame"; + + public FrameDsc() { + initFrame(); + } + + public FrameDsc( int nHeight, int nWidth ) { + height = nHeight; + width = nWidth; + initFrame(); + } + + @Override + public String getName() { + return null; + } + @Override + public String getIfcName() { + return ifcName; + } + @Override + public String getService() { + return service; + } + + private void initFrame() { + try { + ifcClass = Class.forName( ifcName ); + } + catch( ClassNotFoundException cnfE ) { + } + } + @Override + public XInterface createInstance( XMultiServiceFactory docMSF ) { + Object SrvObj = null; + + Size size = new Size(); + size.Height = height; + size.Width = width; + + try { + SrvObj = docMSF.createInstance( service ); + } + catch( com.sun.star.uno.Exception cssuE ){ + } + XShape shape = UnoRuntime.queryInterface( XShape.class, SrvObj ); + try { + shape.setSize(size); + } + catch( com.sun.star.beans.PropertyVetoException pvE ){ + } + + XTextFrame TF = (XTextFrame)UnoRuntime.queryInterface( ifcClass, SrvObj ); + + XPropertySet oPropSet = UnoRuntime.queryInterface( XPropertySet.class, SrvObj ); + + + try { + oPropSet.setPropertyValue("AnchorType", Integer.valueOf(2)); + } + catch( com.sun.star.beans.UnknownPropertyException upE ){ + } + catch( com.sun.star.beans.PropertyVetoException pvE ){ + } + catch( com.sun.star.lang.IllegalArgumentException iaE ){ + } + catch( com.sun.star.lang.WrappedTargetException wtE ){ + } + + + + return TF; + } +} diff --git a/qadevOOo/runner/util/InstCreator.java b/qadevOOo/runner/util/InstCreator.java new file mode 100644 index 000000000..d517f0cd1 --- /dev/null +++ b/qadevOOo/runner/util/InstCreator.java @@ -0,0 +1,104 @@ +/* + * 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 util; + +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XInterface; +import com.sun.star.text.XTextTablesSupplier; +import com.sun.star.text.XTextFramesSupplier; +import com.sun.star.text.XTextSectionsSupplier; +import com.sun.star.text.XFootnotesSupplier; +import com.sun.star.text.XBookmarksSupplier; +import com.sun.star.container.XNameAccess; +import com.sun.star.container.XIndexAccess; + + +public class InstCreator implements XInstCreator { + private final XInterface xParent; + private final XMultiServiceFactory xMSF; + private final XInterface xInstance; + private final XIndexAccess xIA; + private final InstDescr iDsc; + + public InstCreator( XInterface xParent, InstDescr iDsc ) { + this.xParent = xParent; + this.iDsc = iDsc; + + xMSF = UnoRuntime.queryInterface( + XMultiServiceFactory.class, xParent ); + + xInstance = createInstance(); + xIA = createCollection(); + } + public XInterface getInstance() { + return xInstance; + } + + public XInterface createInstance() { + XInterface xIfc = null; + xIfc = iDsc.createInstance( xMSF ); + + return xIfc; + } + + public XIndexAccess getCollection() { + return xIA; + } + + private XIndexAccess createCollection() { + XNameAccess oNA = null; + + if ( iDsc instanceof TableDsc ) { + XTextTablesSupplier oTTS = UnoRuntime.queryInterface( + XTextTablesSupplier.class, xParent ); + + oNA = oTTS.getTextTables(); + } + if ( iDsc instanceof FrameDsc ) { + XTextFramesSupplier oTTS = UnoRuntime.queryInterface( + XTextFramesSupplier.class, xParent ); + + oNA = oTTS.getTextFrames(); + } + if ( iDsc instanceof BookmarkDsc ) { + XBookmarksSupplier oTTS = UnoRuntime.queryInterface( + XBookmarksSupplier.class, xParent ); + + oNA = oTTS.getBookmarks(); + } + + if ( iDsc instanceof FootnoteDsc ) { + XFootnotesSupplier oTTS = UnoRuntime.queryInterface( + XFootnotesSupplier.class, xParent ); + + return oTTS.getFootnotes(); + } + + if ( iDsc instanceof TextSectionDsc ) { + XTextSectionsSupplier oTSS = UnoRuntime.queryInterface( + XTextSectionsSupplier.class, xParent ); + + oNA = oTSS.getTextSections(); + } + + return UnoRuntime.queryInterface( + XIndexAccess.class, oNA); + } +}
\ No newline at end of file diff --git a/qadevOOo/runner/util/InstDescr.java b/qadevOOo/runner/util/InstDescr.java new file mode 100644 index 000000000..7b7098be6 --- /dev/null +++ b/qadevOOo/runner/util/InstDescr.java @@ -0,0 +1,38 @@ +/* + * 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 util; + +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.uno.XInterface; +/** + * the class InstDescr + */ +abstract public class InstDescr { + + protected Class<?> ifcClass = null; + + protected abstract String getIfcName(); + protected abstract String getName(); + + /** + * the method getService + */ + protected abstract String getService(); + protected abstract XInterface createInstance( XMultiServiceFactory docMSF ); +}
\ No newline at end of file diff --git a/qadevOOo/runner/util/ParagraphDsc.java b/qadevOOo/runner/util/ParagraphDsc.java new file mode 100644 index 000000000..12ec3bf12 --- /dev/null +++ b/qadevOOo/runner/util/ParagraphDsc.java @@ -0,0 +1,73 @@ +/* + * 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 util; + +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.uno.XInterface; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.text.XTextContent; + +/** + * the class ParagraphDsc + */ +public class ParagraphDsc extends InstDescr { + + private static final String service = "com.sun.star.text.Paragraph"; + private static final String ifcName = "com.sun.star.text.XTextContent"; + + public ParagraphDsc() { + initParagraph(); + } + + @Override + public String getName() { + return null; + } + + @Override + public String getIfcName() { + return ifcName; + } + + @Override + public String getService() { + return service; + } + + private void initParagraph() { + try { + ifcClass = Class.forName( ifcName ); + } + catch( ClassNotFoundException cnfE ) { + } + } + @Override + public XInterface createInstance( XMultiServiceFactory docMSF ) { + Object ServiceObj = null; + + try { + ServiceObj = docMSF.createInstance( service ); + } + catch( com.sun.star.uno.Exception cssuE ){ + } + XTextContent PG = (XTextContent)UnoRuntime.queryInterface( ifcClass, + ServiceObj ); + return PG; + } +} diff --git a/qadevOOo/runner/util/PropertyName.java b/qadevOOo/runner/util/PropertyName.java new file mode 100644 index 000000000..4812bd7f6 --- /dev/null +++ b/qadevOOo/runner/util/PropertyName.java @@ -0,0 +1,117 @@ +/* + * 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 util; + +/** + * This interfaces describes some key names which are used in <CODE>lib.TestParameters</CODE>. + */ + +public interface PropertyName { + /** + * parameter name: "AppExecutionCommand" + * The AppExecutionCmd contains the full qualified<br> + * command to an Application to be started. + */ + String APP_EXECUTION_COMMAND = "AppExecutionCommand"; + /** + * parameter name: "ConnectionString" + */ + String CONNECTION_STRING = "ConnectionString"; + String PIPE_CONNECTION_STRING = "PipeConnectionString"; + String USE_PIPE_CONNECTION = "UsePipeConnection"; + + /** + * parameter name: "TestBase" + * The Testbase to be executed by the runner<br> + * default is 'java_fat' + */ + String TEST_BASE = "TestBase"; + /** + * parameter name: "TestDocumentPath" + */ + String TEST_DOCUMENT_PATH = "TestDocumentPath"; + /** + * parameter name: "LoggingIsActive" + * 'true' is a log should be written, 'false' elsewhere <br> + * these will be provided by the testcases<br> + * default is true + */ + String LOGGING_IS_ACTIVE = "LoggingIsActive"; + /** + * parameter name: "DebugIsActive" + */ + String DEBUG_IS_ACTIVE = "DebugIsActive"; + /** + * parameter name: "OutProducer" + * This parameter contains the class used<br> + * for Logging + */ + String OUT_PRODUCER = "OutProducer"; + /** + * internal only, no parameter + * The OfficeProvider contains the full qualified + * class that provides a connection to StarOffice<br> + * default is helper.OfficeProvider + */ + String OFFICE_PROVIDER = "OfficeProvider"; + /** + * internal only, no parameter + */ + String OFFICE_WATCHER = "Watcher"; + /** + * internal only, no parameter + * This parameter contains the class used<br> + * for Logging + */ + String LOG_WRITER = "LogWriter"; + /** + * parameter name: "TimeOut"<p> + * time out given in milliseconds + * This parameter contains the timeout used<br> + * by the watcher + */ + String TIME_OUT = "TimeOut"; + /** + * parameter name: "ThreadTimeOut" + * This parameter contains the timeout used<br> + * by the complex tests + */ + String THREAD_TIME_OUT = "ThreadTimeOut"; + /** + * parameter name: "UnoRcName" + */ + String UNORC_NAME = "UnoRcName"; + /** + * parameter name: "AutoRestart" + * If this parameter is <CODE>true</CODE> the <CODE>OfficeProvider</CODE> tries + * to get the URL to the binary of the office and to fill the + * <CODE>AppExecutionCommand</CODE> with useful content if needed. + * Default is false. + */ + String AUTO_RESTART = "AutoRestart"; + /** + * parameter name: "NewOfficeInstance" + */ + String NEW_OFFICE_INSTANCE = "NewOfficeInstance"; + + /** + * parameter name: "SRC_ROOT"<p> + * path to the source root of OpenOffice.org + */ + String SRC_ROOT = "SRC_ROOT"; +} diff --git a/qadevOOo/runner/util/RegistryTools.java b/qadevOOo/runner/util/RegistryTools.java new file mode 100644 index 000000000..72ef5e743 --- /dev/null +++ b/qadevOOo/runner/util/RegistryTools.java @@ -0,0 +1,359 @@ +/* + * 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 util; + +// access the implementations via names +import com.sun.star.uno.UnoRuntime; +import java.io.PrintWriter ; + +import com.sun.star.registry.XRegistryKey ; +import com.sun.star.registry.XSimpleRegistry ; +import com.sun.star.registry.RegistryKeyType ; +import com.sun.star.registry.RegistryValueType ; +import com.sun.star.registry.InvalidRegistryException ; +import com.sun.star.lang.XMultiServiceFactory ; +import com.sun.star.uno.Exception; + +public class RegistryTools { + + /** + * Creates 'com.sun.star.registry.SimpleRegistry' + * service. + * @param xMSF Multiservice factory. + * @return Service created. + */ + public static XSimpleRegistry createRegistryService + (XMultiServiceFactory xMSF) throws com.sun.star.uno.Exception { + + Object oInterface = xMSF.createInstance + ("com.sun.star.registry.SimpleRegistry"); + return UnoRuntime.queryInterface ( + XSimpleRegistry.class, oInterface) ; + } + + /** + * Opens registry file for reading/writing. If file doesn't + * exist a new one created. + * @param file Registry file name. + * @param xMSF Multiservice factory. + * @return Opened registry. + */ + public static XSimpleRegistry openRegistry + (String file, XMultiServiceFactory xMSF) + throws com.sun.star.uno.Exception { + + XSimpleRegistry reg = createRegistryService(xMSF) ; + + reg.open(file, false, true) ; + + return reg ; + } + + /** + * Compares two registry keys, their names, value + * types and values. + * return <code>true</code> if key names, value types + * and values are equal, else returns <code>false</code>. + */ + private static boolean compareKeys + (XRegistryKey key1, XRegistryKey key2) { + + if (key1 == null || key2 == null || + !key1.isValid() || !key2.isValid()) + + return false ; + + String keyName1 = getShortKeyName(key1.getKeyName()) ; + String keyName2 = getShortKeyName(key2.getKeyName()) ; + + if (!keyName1.equals(keyName2)) return false ; + + try { + if (key1.getValueType() != key2.getValueType()) return false ; + } catch (InvalidRegistryException e) { + return false ; + } + + RegistryValueType type ; + try { + type = key1.getValueType() ; + + if (type.equals(RegistryValueType.ASCII)) { + if (!key1.getAsciiValue().equals(key2.getAsciiValue())) + return false ; + } else + if (type.equals(RegistryValueType.STRING)) { + if (!key1.getStringValue().equals(key2.getStringValue())) + return false ; + } else + if (type.equals(RegistryValueType.LONG)) { + if (key1.getLongValue() != key2.getLongValue()) + return false ; + } else + if (type.equals(RegistryValueType.BINARY)) { + byte[] bin1 = key1.getBinaryValue() ; + byte[] bin2 = key2.getBinaryValue() ; + if (bin1.length != bin2.length) + return false ; + for (int i = 0; i < bin1.length; i++) + if (bin1[i] != bin2[i]) return false ; + } else + if (type.equals(RegistryValueType.ASCIILIST)) { + String[] list1 = key1.getAsciiListValue() ; + String[] list2 = key2.getAsciiListValue() ; + if (list1.length != list2.length) + return false ; + for (int i = 0; i < list1.length; i++) + if (!list1[i].equals(list2[i])) return false ; + } else + if (type.equals(RegistryValueType.STRINGLIST)) { + String[] list1 = key1.getStringListValue() ; + String[] list2 = key2.getStringListValue() ; + if (list1.length != list2.length) + return false ; + for (int i = 0; i < list1.length; i++) + if (!list1[i].equals(list2[i])) return false ; + } else + if (type.equals(RegistryValueType.LONGLIST)) { + int[] list1 = key1.getLongListValue() ; + int[] list2 = key2.getLongListValue() ; + if (list1.length != list2.length) + return false ; + for (int i = 0; i < list1.length; i++) + if (list1[i] != list2[i]) return false ; + } + } catch (Exception e) { + return false ; + } + + return true ; + } + + /** + * Gets name of the key relative to its parent. + * For example if full name of key is '/key1/subkey' + * short key name is 'subkey' + * @param keyName Full key name. + * @return Short key name. + */ + private static String getShortKeyName(String keyName) { + if (keyName == null) return null ; + int idx = keyName.lastIndexOf('/') ; + if (idx < 0) return keyName ; + else return keyName.substring(idx + 1) ; + } + + /** + * Compare all child keys. + * @param compareRoot If <code>true</code> method also + * compare root keys, if <code>false</code> it begins recursive + * comparing from children of root keys. + * @return <code>true</code> if keys and their sub keys are equal. + */ + private static boolean compareKeyTrees + (XRegistryKey tree1, XRegistryKey tree2, boolean compareRoot) { + + if (compareRoot && !compareKeys(tree1, tree2)) return false ; + + try { + String[] keyNames1 = tree1.getKeyNames() ; + String[] keyNames2 = tree2.getKeyNames() ; + + if (keyNames1 == null && keyNames2 == null) return true ; + + if (keyNames1 == null || keyNames2 == null || + keyNames2.length != keyNames1.length) + return false ; + + for (int i = 0; i < keyNames1.length; i++) { + + String keyName = getShortKeyName(keyNames1[i]) ; + XRegistryKey key2 = tree2.openKey(keyName) ; + + if (key2 == null) + // key with the same name doesn't exist in the second tree + return false ; + + if (!tree1.getKeyType(keyName).equals( + tree2.getKeyType(keyName))) + return false ; + + if (tree1.getKeyType(keyName).equals( + RegistryKeyType.LINK)) { + + if (!getShortKeyName(tree1.getLinkTarget(keyName)).equals( + getShortKeyName(tree2.getLinkTarget(keyName)))) + + return false ; + } else { + + if (!compareKeyTrees(tree1.openKey(keyName), + tree2.openKey(keyName), true)) return false ; + } + } + } catch (InvalidRegistryException e) { + return false ; + } + + return true ; + } + + /** + * Compare keys specified and all their child keys. + * @return <code>true</code> if keys and their sub keys are equal. + */ + public static boolean compareKeyTrees + (XRegistryKey tree1, XRegistryKey tree2) { + + return compareKeyTrees(tree1, tree2, false) ; + } + + /** + * Prints to a specified output about all keys and subkeys information + * (key name, type, value, link target, attributes) recursively. + * @param reg Registry for which information is needed. + * @param out Output stream. + */ + public static void printRegistryInfo(XSimpleRegistry reg, PrintWriter out) { + try { + printRegistryInfo(reg.getRootKey(), out) ; + } catch (com.sun.star.registry.InvalidRegistryException e) { + out.println("!!! Can't open root registry key for info printing") ; + } + } + + /** + * Prints to a specified output about all keys and subkeys information + * (key name, type, value, link target, attributes) recursively. + * @param root Key for which subkeys (and further) information is required. + * @param out Output stream. + */ + public static void printRegistryInfo(XRegistryKey root, PrintWriter out) { + if (root == null) { + out.println("/(null)") ; + return ; + } + + out.println("/") ; + try { + printTreeInfo(root, out, " ") ; + } catch (com.sun.star.registry.InvalidRegistryException e) { + out.println("Exception accessing registry :") ; + e.printStackTrace(out) ; + } + } + + private static void printTreeInfo(XRegistryKey key, + PrintWriter out, String margin) + throws com.sun.star.registry.InvalidRegistryException { + + String[] subKeys = key.getKeyNames() ; + + if (subKeys == null || subKeys.length == 0) return ; + + for (int i = 0; i < subKeys.length; i++) { + printKeyInfo(key, subKeys[i], out, margin) ; + XRegistryKey subKey = key.openKey + (getShortKeyName(subKeys[i])) ; + printTreeInfo(subKey, out, margin + " ") ; + subKey.closeKey() ; + } + } + + private static void printKeyInfo(XRegistryKey parentKey, + String keyName, PrintWriter out, String margin) + throws com.sun.star.registry.InvalidRegistryException { + + out.print(margin) ; + keyName = getShortKeyName(keyName) ; + XRegistryKey key = parentKey.openKey(keyName) ; + if (key != null) + out.print("/" + getShortKeyName(key.getKeyName()) + " ") ; + else { + out.println("(null)") ; + return ; + } + + if (!key.isValid()) { + out.println("(not valid)") ; + return ; + } + + if (key.isReadOnly()) { + out.print("(read only) ") ; + } + + if (parentKey.getKeyType(keyName) == RegistryKeyType.LINK) { + out.println("(link to " + parentKey.getLinkTarget(keyName) + ")") ; + return ; + } + + RegistryValueType type ; + try { + type = key.getValueType() ; + + if (type.equals(RegistryValueType.ASCII)) { + out.println("[ASCII] = '" + key.getAsciiValue() + "'") ; + } else + if (type.equals(RegistryValueType.STRING)) { + out.println("[STRING] = '" + key.getStringValue() + "'") ; + } else + if (type.equals(RegistryValueType.LONG)) { + out.println("[LONG] = " + key.getLongValue()) ; + } else + if (type.equals(RegistryValueType.BINARY)) { + out.print("[BINARY] = {") ; + byte[] bin = key.getBinaryValue() ; + for (int i = 0; i < bin.length; i++) + out.print(bin[i] + ",") ; + out.println("}") ; + } else + if (type.equals(RegistryValueType.ASCIILIST)) { + out.print("[ASCIILIST] = {") ; + String[] list = key.getAsciiListValue() ; + for (int i = 0; i < list.length; i++) + out.print("'" + list[i] + "',") ; + out.println("}") ; + } else + if (type.equals(RegistryValueType.STRINGLIST)) { + out.print("[STRINGLIST] = {") ; + String[] list = key.getStringListValue() ; + for (int i = 0; i < list.length; i++) + out.print("'" + list[i] + "',") ; + out.println("}") ; + } else + if (type.equals(RegistryValueType.LONGLIST)) { + out.print("[LONGLIST] = {") ; + int[] list = key.getLongListValue() ; + for (int i = 0; i < list.length; i++) + out.print(list[i] + ",") ; + out.println("}") ; + } else { + out.println("") ; + } + } catch (com.sun.star.uno.Exception e) { + out.println("Exception occurred : ") ; + e.printStackTrace(out) ; + } finally { + key.closeKey() ; + } + } + + +} diff --git a/qadevOOo/runner/util/SOfficeFactory.java b/qadevOOo/runner/util/SOfficeFactory.java new file mode 100644 index 000000000..43667d15d --- /dev/null +++ b/qadevOOo/runner/util/SOfficeFactory.java @@ -0,0 +1,443 @@ +/* + * 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 util; + +import java.util.HashMap; +// access the implementations via names +import com.sun.star.uno.XInterface; +import com.sun.star.lang.XMultiServiceFactory; + +import com.sun.star.uno.UnoRuntime; +// staroffice interfaces to provide desktop and componentloader +// and components i.e. spreadsheets, writerdocs etc. +import com.sun.star.frame.XDesktop; +import com.sun.star.frame.XComponentLoader; +import com.sun.star.lang.XComponent; +// name - value pair +import com.sun.star.beans.PropertyValue; +import com.sun.star.beans.PropertyState; + +// additional classes required for testcase +import com.sun.star.sheet.*; +import com.sun.star.text.*; +import com.sun.star.container.*; +import com.sun.star.chart.*; +import com.sun.star.drawing.*; + +public class SOfficeFactory { + + private static HashMap<String, SOfficeFactory> lookup = new HashMap<String, SOfficeFactory>(10); + private final XComponentLoader oCLoader; + + private SOfficeFactory(XMultiServiceFactory xMSF) { + // get XInterface of Desktop service + Object oInterface; + try { + oInterface = xMSF.createInstance("com.sun.star.frame.Desktop"); + } catch (com.sun.star.uno.Exception e) { + throw new IllegalArgumentException("Desktop Service not available", e); + } + + // query the desktop interface and then it's componentloader + XDesktop oDesktop = UnoRuntime.queryInterface( + XDesktop.class, oInterface); + + oCLoader = UnoRuntime.queryInterface( + XComponentLoader.class, oDesktop); + } + + public static SOfficeFactory getFactory(XMultiServiceFactory xMSF) { + + SOfficeFactory soFactory = lookup.get(Integer.toString(xMSF.hashCode())); + + if (soFactory == null) { + soFactory = new SOfficeFactory(xMSF); + lookup.put(Integer.toString(xMSF.hashCode()), soFactory); + } + + return soFactory; + } + + // ********************************************************* + // Document creation. The documents needed are created here. + // ********************************************************* + /** + * method which opens a new TextDocument + * + * @see XTextDocument + */ + public XTextDocument createTextDoc(String frameName) + throws com.sun.star.uno.Exception { + + XComponent oDoc = openDoc("swriter", frameName); + + if (oDoc != null) { + DesktopTools.bringWindowToFront(oDoc); + return UnoRuntime.queryInterface(XTextDocument.class, oDoc); + } else { + return null; + } + + } // finished createTextDoc + + + + /** + * method which opens a new SpreadsheetDocument + * + * @see XSpreadsheetDocument + */ + public XSpreadsheetDocument createCalcDoc(String frameName) + throws com.sun.star.uno.Exception { + + XComponent oDoc = openDoc("scalc", frameName); + + if (oDoc != null) { + DesktopTools.bringWindowToFront(oDoc); + return UnoRuntime.queryInterface(XSpreadsheetDocument.class, oDoc); + } else { + return null; + } + } // finished createCalcDoc + + + + /** + * method which opens a new DrawDocument + */ + public XComponent createDrawDoc(String frameName) + throws com.sun.star.uno.Exception { + + return openDoc("sdraw", frameName); + } // finished createDrawDoc + + + + /** + * method which opens a new ImpressDocument + */ + public XComponent createImpressDoc(String frameName) + throws com.sun.star.uno.Exception { + + return openDoc("simpress", frameName); + } // finished createImpressDoc + + + + /** + * method which opens a new MathDocument + */ + public XComponent createMathDoc(String frameName) + throws com.sun.star.uno.Exception { + + return openDoc("smath", frameName); + } // finished createMathDoc + + + + /** + * method which opens a new ChartDocument + * + * @see XChartDocument + */ + public XChartDocument createChartDoc() + throws com.sun.star.uno.Exception { + + XComponent oDoc = loadDocument("private:factory/schart"); + + if (oDoc != null) { + DesktopTools.bringWindowToFront(oDoc); + XChartDocument xChartDoc = UnoRuntime.queryInterface(XChartDocument.class, oDoc); + // Create a default chart which many chart tests rely on. + com.sun.star.chart2.XChartDocument xCD2 = + UnoRuntime.queryInterface(com.sun.star.chart2.XChartDocument.class, oDoc); + xCD2.createDefaultChart(); + return xChartDoc; + } else { + return null; + } + + } // finished createChartDoc + + /** + * creates a simple TextTable defaulted to 2 rows and 2 columns + */ + public static XTextTable createTextTable(XTextDocument xTextDoc) + { + + TableDsc tDsc = new TableDsc(); + InstCreator instCreate = new InstCreator(xTextDoc, tDsc); + + XTextTable oTable = (XTextTable) instCreate.getInstance(); + return oTable; + } + + /** + * creates a TextTable with a specified count of rows and columns + */ + public static XTextTable createTextTable(XTextDocument xTextDoc, + int rows, int columns) + { + + TableDsc tDsc = new TableDsc(rows, columns); + InstCreator instCreate = new InstCreator(xTextDoc, tDsc); + + XTextTable oTable = (XTextTable) instCreate.getInstance(); + return oTable; + } + + + + /** + * creates a simple TextFrame + * ... to be continued + */ + public static XTextFrame createTextFrame(XTextDocument xTextDoc, + int height, int width) { + + FrameDsc tDsc = new FrameDsc(height, width); + InstCreator instCreate = new InstCreator(xTextDoc, tDsc); + + XTextFrame oFrame = (XTextFrame) instCreate.getInstance(); + return oFrame; + } + + + + public static void insertTextContent(XTextDocument xTextDoc, + XTextContent xCont) + throws com.sun.star.lang.IllegalArgumentException { + XText xText = xTextDoc.getText(); + XText oText = UnoRuntime.queryInterface( + XText.class, xText); + + XTextCursor oCursor = oText.createTextCursor(); + oText.insertTextContent(oCursor, xCont, false); + } + + public static com.sun.star.table.XCell getFirstTableCell( + XTextContent oTable) { + + String CellNames[] = ((XTextTable) oTable).getCellNames(); + + com.sun.star.table.XCell oCell = ((XTextTable) oTable).getCellByName( + CellNames[0]); + return oCell; + + } + + /** + * the method createBookmark + */ + public static XTextContent createBookmark(XTextDocument xTextDoc) + { + + BookmarkDsc tDsc = new BookmarkDsc(); + InstCreator instCreate = new InstCreator(xTextDoc, tDsc); + + XTextContent oBookmark = (XTextContent) instCreate.getInstance(); + return oBookmark; + + } /// finish createBookmark + + + + + + /** + * the method create Index + */ + public static XTextContent createIndex(XTextDocument xTextDoc, String kind) + throws com.sun.star.uno.Exception { + + XMultiServiceFactory oDocMSF = UnoRuntime.queryInterface(XMultiServiceFactory.class, + xTextDoc); + + Object oInt = oDocMSF.createInstance(kind); + + XTextContent xTC = UnoRuntime.queryInterface(XDocumentIndex.class, oInt); + + return xTC; + + } + + public static XSpreadsheet createSpreadsheet(XSpreadsheetDocument oDoc) + throws com.sun.star.uno.Exception { + + XMultiServiceFactory oDocMSF = UnoRuntime.queryInterface(XMultiServiceFactory.class, oDoc); + + Object oInt = oDocMSF.createInstance( + "com.sun.star.sheet.Spreadsheet"); + + XSpreadsheet oSpreadsheet = UnoRuntime.queryInterface(XSpreadsheet.class, oInt); + + return oSpreadsheet; + } + + public static XIndexAccess getTableCollection(XTextDocument oDoc) { + + XTextTablesSupplier oTTS = UnoRuntime.queryInterface(XTextTablesSupplier.class, oDoc); + + XNameAccess oNA = oTTS.getTextTables(); + XIndexAccess oIA = UnoRuntime.queryInterface(XIndexAccess.class, oNA); + + return oIA; + } + + + + public XShape createShape(XComponent oDoc, int height, int width, int x, int y, String kind) { + //possible values for kind are 'Ellipse', 'Line' and 'Rectangle' + + ShapeDsc sDsc = new ShapeDsc(height, width, x, y, kind); + InstCreator instCreate = new InstCreator(oDoc, sDsc); + + XShape oShape = (XShape) instCreate.getInstance(); + + return oShape; + + } + + /** + * creates a Diagram as specified in kind + */ + public XDiagram createDiagram(XComponent oDoc, String kind) { + XInterface oInterface = null; + XDiagram oDiagram = null; + + //get LineDiagram + XMultiServiceFactory oDocMSF = UnoRuntime.queryInterface(XMultiServiceFactory.class, oDoc); + + try { + oInterface = (XInterface) oDocMSF.createInstance("com.sun.star.chart." + kind); + oDiagram = UnoRuntime.queryInterface(XDiagram.class, oInterface); + } catch (Exception e) { + // Some exception occurs.FAILED + System.out.println("Couldn't create " + kind + "-Diagram " + e); + } + return oDiagram; + } + + /** + * creates a control instance as specified in kind + */ + public XInterface createControl(XComponent oDoc, String kind) { + + XInterface oControl = null; + + XMultiServiceFactory oDocMSF = UnoRuntime.queryInterface(XMultiServiceFactory.class, oDoc); + + try { + oControl = (XInterface) oDocMSF.createInstance("com.sun.star.form.component." + kind); + } catch (Exception e) { + // Some exception occurs.FAILED + System.out.println("Couldn't create instance " + kind + ": " + e); + } + return oControl; + } + + /** + * create an Instance as specified in kind + */ + public Object createInstance(XComponent oDoc, String kind) { + + Object oInstance = null; + + XMultiServiceFactory oDocMSF = UnoRuntime.queryInterface(XMultiServiceFactory.class, oDoc); + + try { + oInstance = oDocMSF.createInstance(kind); + } catch (Exception e) { + // Some exception occurs.FAILED + System.out.println("Couldn't create instance " + kind + ": " + e); + } + return oInstance; + } + + + + public XComponent loadDocument(String fileName) + throws com.sun.star.lang.IllegalArgumentException, + com.sun.star.io.IOException, + com.sun.star.uno.Exception { + + // that noargs thing for load attributes + PropertyValue[] szEmptyArgs = new PropertyValue[0]; + String frameName = "_blank"; + + XComponent oDoc = oCLoader.loadComponentFromURL( + fileName, frameName, 0, szEmptyArgs); + + if (oDoc == null) { + return null; + } + DesktopTools.bringWindowToFront(oDoc); + return oDoc; + } + + public XComponent loadDocument(String fileName, PropertyValue[] Args) + throws com.sun.star.lang.IllegalArgumentException, + com.sun.star.io.IOException, + com.sun.star.uno.Exception { + + // that noargs thing for load attributes + String frameName = "_blank"; + + XComponent oDoc = oCLoader.loadComponentFromURL( + fileName, frameName, 0, Args); + + if (oDoc == null) { + return null; + } + DesktopTools.bringWindowToFront(oDoc); + + return oDoc; + } + + public XComponent openDoc(String kind, String frameName) + throws com.sun.star.lang.IllegalArgumentException, + com.sun.star.io.IOException, + com.sun.star.uno.Exception { + + // that noargs thing for load attributes + PropertyValue[] Args = null; + if (kind.equals("simpress")) { + Args = new PropertyValue[1]; + PropertyValue Arg = new PropertyValue(); + Arg.Name = "OpenFlags"; + Arg.Value = "S"; + Arg.Handle = -1; + Arg.State = PropertyState.DEFAULT_VALUE; + Args[0] = Arg; + } else { + Args = new PropertyValue[0]; + } + + if (frameName == null) { + frameName = "_blank"; + } + // load a blank a doc + XComponent oDoc = oCLoader.loadComponentFromURL("private:factory/" + kind, frameName, 40, Args); + DesktopTools.bringWindowToFront(oDoc); + + return oDoc; + + } // finished openDoc + + +} diff --git a/qadevOOo/runner/util/ShapeDsc.java b/qadevOOo/runner/util/ShapeDsc.java new file mode 100644 index 000000000..e47128172 --- /dev/null +++ b/qadevOOo/runner/util/ShapeDsc.java @@ -0,0 +1,97 @@ +/* + * 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 util; + +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.uno.XInterface; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.drawing.*; +import com.sun.star.awt.*; +/** + * the class TableDsc + */ +public class ShapeDsc extends InstDescr { + + private final int x; + private final int y; + private final int height; + private final int width; + private static final String name = null; + private static final String ifcName = "com.sun.star.drawing.XShape"; + private final String service; + + public ShapeDsc(int nheight, int nwidth, int nx, int ny, String kind) { + x = nx; + y = ny; + height = nheight; + width = nwidth; + service = "com.sun.star.drawing." + kind + "Shape"; + initShape(); + } + + @Override + public String getName() { + return name; + } + + @Override + public String getIfcName() { + return ifcName; + } + @Override + public String getService() { + return service; + } + + private void initShape() { + try { + ifcClass = Class.forName( ifcName ); + } + catch( ClassNotFoundException cnfE ) { + } + } + @Override + public XInterface createInstance( XMultiServiceFactory docMSF ) { + + + Object SrvObj = null; + try { + SrvObj = docMSF.createInstance( service ); + } + catch( com.sun.star.uno.Exception cssuE ){ + } + + XShape Sh = (XShape)UnoRuntime.queryInterface(ifcClass, SrvObj ); + Size size = new Size(); + Point position = new Point(); + size.Height = height; + size.Width = width; + position.X = x; + position.Y = y; + try { + Sh.setSize(size); + Sh.setPosition(position); + } + catch ( com.sun.star.beans.PropertyVetoException e) { + } + + return Sh; + + } +}
\ No newline at end of file diff --git a/qadevOOo/runner/util/SysUtils.java b/qadevOOo/runner/util/SysUtils.java new file mode 100644 index 000000000..2b02fd79b --- /dev/null +++ b/qadevOOo/runner/util/SysUtils.java @@ -0,0 +1,60 @@ +/* + * 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 util; + +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.datatransfer.clipboard.*; +import com.sun.star.datatransfer.*; + +public class SysUtils { + + /** + * Tries to obtain text data from clipboard if such one exists. + * The method iterates through all 'text/plain' supported data + * flavors and returns the first non-null String value. + * + * @param msf MultiserviceFactory + * @return First found string clipboard contents or null if no + * text contents were found. + * @throws com.sun.star.uno.Exception if system clipboard is not accessible. + */ + public static String getSysClipboardText(XMultiServiceFactory msf) + throws com.sun.star.uno.Exception { + + XClipboard xCB = UnoRuntime.queryInterface + (XClipboard.class, msf.createInstance + ("com.sun.star.datatransfer.clipboard.SystemClipboard")); + + XTransferable xTrans = xCB.getContents(); + + DataFlavor[] dfs = xTrans.getTransferDataFlavors(); + + for (int i = 0; i < dfs.length; i++) { + if (dfs[i].MimeType.startsWith("text/plain")) { + Object data = xTrans.getTransferData(dfs[i]); + if (data instanceof String) { + return (String) data; + } + } + } + + return null; + } +} diff --git a/qadevOOo/runner/util/TableDsc.java b/qadevOOo/runner/util/TableDsc.java new file mode 100644 index 000000000..3fef4ebd5 --- /dev/null +++ b/qadevOOo/runner/util/TableDsc.java @@ -0,0 +1,84 @@ +/* + * 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 util; + +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.uno.XInterface; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.text.XTextTable; +/** + * the class TableDsc + */ +public class TableDsc extends InstDescr { + + private int rows = 0; + private int columns = 0; + private static final String ifcName = "com.sun.star.text.XTextTable"; + private static final String service = "com.sun.star.text.TextTable"; + + public TableDsc() { + initTable(); + } + + public TableDsc( int nRows, int nColumns ) { + rows = nRows; + columns = nColumns; + initTable(); + } + + @Override + public String getName() { + return null; + } + @Override + public String getIfcName() { + return ifcName; + } + @Override + public String getService() { + return service; + } + + private void initTable() { + try { + ifcClass = Class.forName( ifcName ); + } + catch( ClassNotFoundException cnfE ) { + } + } + @Override + public XInterface createInstance( XMultiServiceFactory docMSF ) { + Object SrvObj = null; + try { + SrvObj = docMSF.createInstance( service ); + } + catch( com.sun.star.uno.Exception cssuE ){ + } + + XTextTable TT = (XTextTable)UnoRuntime.queryInterface( + ifcClass, SrvObj ); + + if ( rows > 0 && columns > 0 ) { + TT.initialize( rows, columns ); + } + + return TT; + + } +} diff --git a/qadevOOo/runner/util/TextSectionDsc.java b/qadevOOo/runner/util/TextSectionDsc.java new file mode 100644 index 000000000..3a6cce51d --- /dev/null +++ b/qadevOOo/runner/util/TextSectionDsc.java @@ -0,0 +1,72 @@ +/* + * 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 util; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.uno.XInterface; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.text.XTextContent; + +/** + * the class TextSectionDsc + */ +public class TextSectionDsc extends InstDescr { + + private static final String service = "com.sun.star.text.TextSection"; + private static final String ifcName = "com.sun.star.text.XTextContent"; + + public TextSectionDsc() { + initTextSection(); + } + + @Override + public String getName() { + return null; + } + + @Override + public String getIfcName() { + return ifcName; + } + + @Override + public String getService() { + return service; + } + + private void initTextSection() { + try { + ifcClass = Class.forName( ifcName ); + } + catch( ClassNotFoundException cnfE ) { + } + } + @Override + public XInterface createInstance( XMultiServiceFactory docMSF ) { + Object ServiceObj = null; + + try { + ServiceObj = docMSF.createInstance( service ); + } + catch( com.sun.star.uno.Exception cssuE ){ + } + XTextContent PG = (XTextContent)UnoRuntime.queryInterface( ifcClass, + ServiceObj ); + return PG; + } +} diff --git a/qadevOOo/runner/util/UITools.java b/qadevOOo/runner/util/UITools.java new file mode 100644 index 000000000..c9969d355 --- /dev/null +++ b/qadevOOo/runner/util/UITools.java @@ -0,0 +1,218 @@ +/* + * 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 util; + +import java.io.PrintWriter; +import java.util.ArrayList; + +import com.sun.star.accessibility.AccessibleRole; +import com.sun.star.accessibility.XAccessible; +import com.sun.star.accessibility.XAccessibleAction; +import com.sun.star.accessibility.XAccessibleContext; +import com.sun.star.accessibility.XAccessibleEditableText; +import com.sun.star.accessibility.XAccessibleText; +import com.sun.star.accessibility.XAccessibleValue; +import com.sun.star.awt.XWindow; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XInterface; + +/** + * This class supports some functions to handle easily accessible objects + */ +public class UITools { + + private final XAccessible mXRoot; + + public UITools(XWindow xWindow) + { + mXRoot = makeRoot(xWindow); + } + + private static String getString(XInterface xInt) + { + XAccessibleText oText = UnoRuntime.queryInterface(XAccessibleText.class, xInt); + return oText.getText(); + } + + private static void setString(XInterface xInt, String cText) + { + XAccessibleEditableText oText = UnoRuntime.queryInterface(XAccessibleEditableText.class, xInt); + + oText.setText(cText); + } + + private static XAccessible makeRoot(XWindow xWindow) + { + return AccessibilityTools.getAccessibleObject(xWindow); + } + + /** + * get the root element of the accessible tree + * @return the root element + */ + public XAccessible getRoot() + { + return mXRoot; + } + + /** + * Helper method: set a text into AccessibleEdit field + * @param textfiledName is the name of the text field + * @param stringToSet is the string to set + * @throws java.lang.Exception if something fail + */ + public void setTextEditFiledText(String textfiledName, String stringToSet) + throws java.lang.Exception + { + XInterface oTextField = AccessibilityTools.getAccessibleObjectForRole(mXRoot, + AccessibleRole.TEXT, textfiledName); + setString(oTextField, stringToSet); + } + + /** + * returns the button by the given name + * @param buttonName is the name of the button to get + * @return a XAccessibleContext of the button + * @throws java.lang.Exception if something fail + */ + public XAccessibleContext getButton(String buttonName) throws java.lang.Exception + { + return AccessibilityTools.getAccessibleObjectForRole + (mXRoot, AccessibleRole.PUSH_BUTTON, buttonName); + } + + /** + * Helper method: gets button via accessibility and 'click' it</code> + * @param buttonName is the name of the button to click + * @throws java.lang.Exception if something fail + */ + public void clickButton(String buttonName) throws java.lang.Exception + { + + XAccessibleContext oButton =AccessibilityTools.getAccessibleObjectForRole + (mXRoot, AccessibleRole.PUSH_BUTTON, buttonName); + if (oButton == null){ + throw new Exception("Could not get button '" + buttonName + "'"); + } + XAccessibleAction oAction = UnoRuntime.queryInterface(XAccessibleAction.class, oButton); + + // "click" the button + try{ + oAction.doAccessibleAction(0); + } catch (com.sun.star.lang.IndexOutOfBoundsException e) { + throw new Exception("Could not do accessible action with '" + + buttonName + "'", e); + } + } + + /** + * Helper method: returns the entry manes of a List-Box + * @param ListBoxName the name of the listbox + * @return the listbox entry names + * @throws java.lang.Exception if something fail + */ + public String[] getListBoxItems(String ListBoxName) + throws java.lang.Exception + { + ArrayList<String> Items = new ArrayList<String>(); + try { + XAccessibleContext xListBox = null; + XAccessibleContext xList = null; + + xListBox =AccessibilityTools.getAccessibleObjectForRole(mXRoot, + AccessibleRole.COMBO_BOX, ListBoxName); + if (xListBox == null){ + xListBox =AccessibilityTools.getAccessibleObjectForRole(mXRoot, + AccessibleRole.PANEL, ListBoxName); + } + + if (xListBox == null){ + // get the list of TreeListBox + xList =AccessibilityTools.getAccessibleObjectForRole(mXRoot, + AccessibleRole.TREE, ListBoxName); + + // all other list boxes have a children of kind of LIST + } else { + + XAccessible xListBoxAccess = UnoRuntime.queryInterface(XAccessible.class, xListBox); + // if a List is not pulled to be open all entries are not visible, therefore the + // boolean argument + xList =AccessibilityTools.getAccessibleObjectForRole( + xListBoxAccess, AccessibleRole.LIST, true); + } + + for (int i=0;i<xList.getAccessibleChildCount();i++) { + try { + XAccessible xChild = xList.getAccessibleChild(i); + XAccessibleContext xChildCont = + xChild.getAccessibleContext(); + XInterface xChildInterface = UnoRuntime.queryInterface(XInterface.class, xChildCont); + Items.add(getString(xChildInterface)); + + } catch (com.sun.star.lang.IndexOutOfBoundsException e) { + throw new Exception("Could not get child form list of '" + + ListBoxName + "'", e); + } + } + + } catch (Exception e) { + throw new Exception("Could not get list of items from '" + + ListBoxName + "'", e); + } + String[]ret = new String[Items.size()]; + return Items.toArray(ret); + } + + /** + * set a value to a named check box + * @param CheckBoxName the name of the check box + * @param Value the value to set + *<ul> + * <li>0: not checked </li> + * <li>1: checked </li> + * <li>2: don't know </li> + *</ul> + * @throws java.lang.Exception if something fail + */ + public void setCheckBoxValue(String CheckBoxName, Integer Value) + throws java.lang.Exception + { + try { + XInterface xCheckBox =AccessibilityTools.getAccessibleObjectForRole(mXRoot, + AccessibleRole.CHECK_BOX, CheckBoxName); + XAccessibleValue xCheckBoxValue = UnoRuntime.queryInterface(XAccessibleValue.class, xCheckBox); + xCheckBoxValue.setCurrentValue(Value); + + } catch (Exception e) { + throw new Exception("Could not set value to CheckBox '" + + CheckBoxName + "'", e); + } + } + + /** + * Prints the accessible tree to the <CODE>logWriter</CODE> only if <CODE>debugIsActive</CODE> + * is set to <CODE>true</CODE> + * @param log logWriter + * @param debugIsActive prints only if this parameter is set to TRUE + */ + public void printAccessibleTree(PrintWriter log, boolean debugIsActive) { + AccessibilityTools.printAccessibleTree(log, mXRoot, debugIsActive); + } + +} diff --git a/qadevOOo/runner/util/ValueChanger.java b/qadevOOo/runner/util/ValueChanger.java new file mode 100644 index 000000000..8a6c51936 --- /dev/null +++ b/qadevOOo/runner/util/ValueChanger.java @@ -0,0 +1,1102 @@ +/* + * 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 util; + +import com.sun.star.awt.Point; +import com.sun.star.beans.PropertyValue; +import com.sun.star.drawing.PolygonFlags; +import com.sun.star.uno.Enum; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.Array; +import com.sun.star.uno.Any; +import com.sun.star.uno.AnyConverter; +import com.sun.star.uno.Type; + +public class ValueChanger { + + // Method to change a Value, thought for properties + public static Object changePValue(Object oldValue, String name) { + + Object newValue = null; + + if (oldValue instanceof com.sun.star.uno.Any) { + try { + oldValue = AnyConverter.toObject(((Any) oldValue).getType(), + oldValue); + } catch (com.sun.star.lang.IllegalArgumentException iae) { + } + } + + if (oldValue == null) + return null; + + if (oldValue instanceof Boolean) { + boolean oldbool = ((Boolean) oldValue).booleanValue(); + newValue = Boolean.valueOf(!oldbool); + } else if (oldValue instanceof Integer) { + int oldint = ((Integer) oldValue).intValue(); + newValue = Integer.valueOf(oldint + 5); + } else if (oldValue instanceof Long) { + long oldlong = ((Long) oldValue).longValue(); + newValue = Long.valueOf(oldlong + 15); + } else if (oldValue instanceof Short) { + short n = ((Short) oldValue).shortValue(); + if ("DefaultState".equals(name) && n == 2) { + // css.form.component.{CheckBox,RadioButton} DefaultState + // properties must have values in the range 0--2: + --n; + } else if ("LinkUpdateMode".equals(name) && n >= 2) { + // css.document.Settings LinkUpdateMode property must have + // values in the css.document.LinkUpdateModes range (0--3), + // while css.sheet.XGlobalSheetSettings LinkUpdateMode property + // must have values in the range 0--2: + --n; + } else { + ++n; + } + newValue = Short.valueOf(n); + } else if (oldValue instanceof Byte) { + byte oldbyte = ((Byte) oldValue).byteValue(); + newValue = Byte.valueOf((byte) (oldbyte + 1)); + } else if (oldValue instanceof Float) { + float oldfloat = ((Float) oldValue).floatValue(); + newValue = new Float((float) (oldfloat + 16.7)); + } else if (oldValue instanceof Double) { + double olddouble = ((Double) oldValue).doubleValue(); + newValue = new Double(olddouble + 17.8); + } else if (oldValue instanceof String) { + String oldString = (String) oldValue; + newValue = oldString + "New"; + } else if (oldValue instanceof com.sun.star.chart.ChartAxisArrangeOrderType) { + Object AO1 = com.sun.star.chart.ChartAxisArrangeOrderType.AUTO; + Object AO2 = com.sun.star.chart.ChartAxisArrangeOrderType.SIDE_BY_SIDE; + Object AO3 = com.sun.star.chart.ChartAxisArrangeOrderType.STAGGER_EVEN; + Object AO4 = com.sun.star.chart.ChartAxisArrangeOrderType.STAGGER_ODD; + + if (oldValue.equals(AO1)) + newValue = AO2; + if (oldValue.equals(AO2)) + newValue = AO3; + if (oldValue.equals(AO3)) + newValue = AO4; + if (oldValue.equals(AO4)) + newValue = AO1; + } else if (oldValue instanceof com.sun.star.view.PaperOrientation) { + Object OR1 = com.sun.star.view.PaperOrientation.LANDSCAPE; + Object OR2 = com.sun.star.view.PaperOrientation.PORTRAIT; + + if (oldValue.equals(OR1)) + newValue = OR2; + else + newValue = OR1; + } else if (oldValue instanceof com.sun.star.lang.Locale) { + com.sun.star.lang.Locale Loc1 = new com.sun.star.lang.Locale( + "en", "US", ""); + com.sun.star.lang.Locale Loc2 = new com.sun.star.lang.Locale( + "de", "DE", ""); + com.sun.star.lang.Locale old = (com.sun.star.lang.Locale) oldValue; + if (old.Language.equals(Loc1.Language) + && old.Country.equals(Loc1.Country) + && old.Variant.equals(Loc1.Variant)) + newValue = Loc2; + else + newValue = Loc1; + } else if (oldValue instanceof com.sun.star.style.ParagraphAdjust) { + Object PA1 = com.sun.star.style.ParagraphAdjust.LEFT; + Object PA2 = com.sun.star.style.ParagraphAdjust.CENTER; + + if (oldValue.equals(PA1)) + newValue = PA2; + else + newValue = PA1; + } else if (oldValue instanceof com.sun.star.style.LineSpacing) { + com.sun.star.style.LineSpacing LS = new com.sun.star.style.LineSpacing(); + com.sun.star.style.LineSpacing LSold = (com.sun.star.style.LineSpacing) oldValue; + LS.Height = (short) ((LSold.Height) + 1); + LS.Mode = (short) ((LSold.Mode) + 1); + newValue = LS; + } else if (oldValue instanceof com.sun.star.drawing.Direction3D) { + com.sun.star.drawing.Direction3D D3D = new com.sun.star.drawing.Direction3D(); + com.sun.star.drawing.Direction3D D3Dold = (com.sun.star.drawing.Direction3D) oldValue; + D3D.DirectionX = D3Dold.DirectionX + .5; + D3D.DirectionY = D3Dold.DirectionY + .5; + D3D.DirectionZ = D3Dold.DirectionZ + .5; + newValue = D3D; + } else if (oldValue instanceof com.sun.star.style.GraphicLocation) { + Object GL1 = com.sun.star.style.GraphicLocation.AREA; + Object GL2 = com.sun.star.style.GraphicLocation.LEFT_BOTTOM; + + if (oldValue.equals(GL1)) + newValue = GL2; + else + newValue = GL1; + } else if (oldValue instanceof com.sun.star.style.TabStop) { + com.sun.star.style.TabStop TS = new com.sun.star.style.TabStop(); + com.sun.star.style.TabStop TSold = (com.sun.star.style.TabStop) oldValue; + com.sun.star.style.TabAlign TA1 = com.sun.star.style.TabAlign.CENTER; + com.sun.star.style.TabAlign TA2 = com.sun.star.style.TabAlign.RIGHT; + + if (TSold.Alignment.equals(TA1)) + TS.Alignment = TA2; + else + TS.Alignment = TA1; + + TS.Position = ((TSold.Position) + 1); + + newValue = TS; + } else if (oldValue instanceof com.sun.star.style.DropCapFormat) { + com.sun.star.style.DropCapFormat DCF = new com.sun.star.style.DropCapFormat(); + com.sun.star.style.DropCapFormat DCFold = (com.sun.star.style.DropCapFormat) oldValue; + DCF.Count = (byte) ((DCFold.Count) + 1); + DCF.Distance = (short) ((DCFold.Distance) + 1); + DCF.Lines = (byte) ((DCFold.Lines) + 1); + newValue = DCF; + } else if (oldValue instanceof com.sun.star.text.TextContentAnchorType) { + com.sun.star.text.TextContentAnchorType TCAT1 = com.sun.star.text.TextContentAnchorType.AS_CHARACTER; + com.sun.star.text.TextContentAnchorType TCAT2 = com.sun.star.text.TextContentAnchorType.AT_CHARACTER; + com.sun.star.text.TextContentAnchorType TCAT3 = com.sun.star.text.TextContentAnchorType.AT_FRAME; + com.sun.star.text.TextContentAnchorType TCAT4 = com.sun.star.text.TextContentAnchorType.AT_PAGE; + com.sun.star.text.TextContentAnchorType TCAT5 = com.sun.star.text.TextContentAnchorType.AT_PARAGRAPH; + if (oldValue.equals(TCAT1)) + newValue = TCAT2; + if (oldValue.equals(TCAT2)) + newValue = TCAT3; + if (oldValue.equals(TCAT3)) + newValue = TCAT4; + if (oldValue.equals(TCAT4)) + newValue = TCAT5; + if (oldValue.equals(TCAT5)) + newValue = TCAT1; + } else if (oldValue instanceof com.sun.star.text.WrapTextMode) { + com.sun.star.text.WrapTextMode WTM1 = com.sun.star.text.WrapTextMode.DYNAMIC; + com.sun.star.text.WrapTextMode WTM2 = com.sun.star.text.WrapTextMode.LEFT; + com.sun.star.text.WrapTextMode WTM3 = com.sun.star.text.WrapTextMode.NONE; + com.sun.star.text.WrapTextMode WTM4 = com.sun.star.text.WrapTextMode.PARALLEL; + com.sun.star.text.WrapTextMode WTM5 = com.sun.star.text.WrapTextMode.RIGHT; + com.sun.star.text.WrapTextMode WTM6 = com.sun.star.text.WrapTextMode.THROUGH; + if (oldValue.equals(WTM1)) + newValue = WTM2; + if (oldValue.equals(WTM2)) + newValue = WTM3; + if (oldValue.equals(WTM3)) + newValue = WTM4; + if (oldValue.equals(WTM4)) + newValue = WTM5; + if (oldValue.equals(WTM5)) + newValue = WTM6; + if (oldValue.equals(WTM6)) + newValue = WTM1; + } else if (oldValue instanceof com.sun.star.awt.Size) { + com.sun.star.awt.Size oldSize = (com.sun.star.awt.Size) oldValue; + com.sun.star.awt.Size newSize = new com.sun.star.awt.Size(); + newSize.Height = oldSize.Height + 1; + newSize.Width = oldSize.Width + 1; + newValue = newSize; + } else if (oldValue instanceof com.sun.star.awt.Rectangle) { + com.sun.star.awt.Rectangle oldRectangle = (com.sun.star.awt.Rectangle) oldValue; + com.sun.star.awt.Rectangle newRectangle = new com.sun.star.awt.Rectangle(); + newRectangle.Height = oldRectangle.Height + 1; + newRectangle.Width = oldRectangle.Width + 1; + newRectangle.X = oldRectangle.Y + 1; + newRectangle.Y = oldRectangle.X + 1; + newValue = newRectangle; + } else if (oldValue instanceof com.sun.star.awt.Point) { + com.sun.star.awt.Point oldPoint = (com.sun.star.awt.Point) oldValue; + com.sun.star.awt.Point newPoint = new com.sun.star.awt.Point(); + newPoint.X = oldPoint.X + 1; + newPoint.Y = oldPoint.Y + 1; + newValue = newPoint; + } else if (oldValue instanceof com.sun.star.table.ShadowFormat) { + com.sun.star.table.ShadowFormat SF = new com.sun.star.table.ShadowFormat(); + com.sun.star.table.ShadowFormat SFold = (com.sun.star.table.ShadowFormat) oldValue; + SF.IsTransparent = (!SFold.IsTransparent); + SF.ShadowWidth = (short) ((SFold.ShadowWidth) + 1); + newValue = SF; + } else if (oldValue instanceof com.sun.star.awt.FontSlant) { + com.sun.star.awt.FontSlant FS1 = com.sun.star.awt.FontSlant.DONTKNOW; + com.sun.star.awt.FontSlant FS2 = com.sun.star.awt.FontSlant.ITALIC; + com.sun.star.awt.FontSlant FS3 = com.sun.star.awt.FontSlant.NONE; + com.sun.star.awt.FontSlant FS4 = com.sun.star.awt.FontSlant.OBLIQUE; + com.sun.star.awt.FontSlant FS5 = com.sun.star.awt.FontSlant.REVERSE_ITALIC; + com.sun.star.awt.FontSlant FS6 = com.sun.star.awt.FontSlant.REVERSE_OBLIQUE; + if (oldValue.equals(FS1)) + newValue = FS2; + if (oldValue.equals(FS2)) + newValue = FS3; + if (oldValue.equals(FS3)) + newValue = FS4; + if (oldValue.equals(FS4)) + newValue = FS5; + if (oldValue.equals(FS5)) + newValue = FS6; + if (oldValue.equals(FS6)) + newValue = FS1; + } else if (oldValue instanceof com.sun.star.table.CellHoriJustify) { + com.sun.star.table.CellHoriJustify CHJ1 = com.sun.star.table.CellHoriJustify.BLOCK; + com.sun.star.table.CellHoriJustify CHJ2 = com.sun.star.table.CellHoriJustify.CENTER; + com.sun.star.table.CellHoriJustify CHJ3 = com.sun.star.table.CellHoriJustify.LEFT; + com.sun.star.table.CellHoriJustify CHJ4 = com.sun.star.table.CellHoriJustify.REPEAT; + com.sun.star.table.CellHoriJustify CHJ5 = com.sun.star.table.CellHoriJustify.RIGHT; + com.sun.star.table.CellHoriJustify CHJ6 = com.sun.star.table.CellHoriJustify.STANDARD; + if (oldValue.equals(CHJ1)) + newValue = CHJ2; + if (oldValue.equals(CHJ2)) + newValue = CHJ3; + if (oldValue.equals(CHJ3)) + newValue = CHJ4; + if (oldValue.equals(CHJ4)) + newValue = CHJ5; + if (oldValue.equals(CHJ5)) + newValue = CHJ6; + if (oldValue.equals(CHJ6)) + newValue = CHJ1; + } else if (oldValue instanceof com.sun.star.table.CellVertJustify) { + com.sun.star.table.CellVertJustify CVJ1 = com.sun.star.table.CellVertJustify.BOTTOM; + com.sun.star.table.CellVertJustify CVJ2 = com.sun.star.table.CellVertJustify.CENTER; + com.sun.star.table.CellVertJustify CVJ3 = com.sun.star.table.CellVertJustify.STANDARD; + com.sun.star.table.CellVertJustify CVJ4 = com.sun.star.table.CellVertJustify.TOP; + if (oldValue.equals(CVJ1)) + newValue = CVJ2; + if (oldValue.equals(CVJ2)) + newValue = CVJ3; + if (oldValue.equals(CVJ3)) + newValue = CVJ4; + if (oldValue.equals(CVJ4)) + newValue = CVJ1; + } else if (oldValue instanceof com.sun.star.table.CellOrientation) { + com.sun.star.table.CellOrientation CO1 = com.sun.star.table.CellOrientation.BOTTOMTOP; + com.sun.star.table.CellOrientation CO2 = com.sun.star.table.CellOrientation.STACKED; + com.sun.star.table.CellOrientation CO3 = com.sun.star.table.CellOrientation.STANDARD; + com.sun.star.table.CellOrientation CO4 = com.sun.star.table.CellOrientation.TOPBOTTOM; + if (oldValue.equals(CO1)) + newValue = CO2; + if (oldValue.equals(CO2)) + newValue = CO3; + if (oldValue.equals(CO3)) + newValue = CO4; + if (oldValue.equals(CO4)) + newValue = CO1; + } else if (oldValue instanceof com.sun.star.util.CellProtection) { + com.sun.star.util.CellProtection CP = new com.sun.star.util.CellProtection(); + com.sun.star.util.CellProtection CPold = (com.sun.star.util.CellProtection) oldValue; + CP.IsFormulaHidden = (!CPold.IsFormulaHidden); + CP.IsHidden = (!CPold.IsHidden); + CP.IsLocked = (!CPold.IsLocked); + CP.IsPrintHidden = (!CPold.IsPrintHidden); + newValue = CP; + } else if (oldValue instanceof com.sun.star.table.TableBorder) { + com.sun.star.table.TableBorder TBold = (com.sun.star.table.TableBorder) oldValue; + com.sun.star.table.TableBorder TB = new com.sun.star.table.TableBorder(); + TB.IsBottomLineValid = (!TBold.IsBottomLineValid); + TB.IsDistanceValid = (!TBold.IsDistanceValid); + TB.IsRightLineValid = (!TBold.IsRightLineValid); + TB.IsTopLineValid = (!TBold.IsTopLineValid); + newValue = TB; + } else if (oldValue instanceof com.sun.star.drawing.FillStyle) { + /* + * if (oldValue instanceof com.sun.star.awt.XBitmap) { newValue = + * new BitmapLoader(); } + */ + com.sun.star.drawing.FillStyle FS1 = com.sun.star.drawing.FillStyle.NONE; + com.sun.star.drawing.FillStyle FS2 = com.sun.star.drawing.FillStyle.SOLID; + com.sun.star.drawing.FillStyle FS3 = com.sun.star.drawing.FillStyle.GRADIENT; + com.sun.star.drawing.FillStyle FS4 = com.sun.star.drawing.FillStyle.HATCH; + com.sun.star.drawing.FillStyle FS5 = com.sun.star.drawing.FillStyle.BITMAP; + if (oldValue.equals(FS1)) + newValue = FS2; + if (oldValue.equals(FS2)) + newValue = FS3; + if (oldValue.equals(FS3)) + newValue = FS4; + if (oldValue.equals(FS4)) + newValue = FS5; + if (oldValue.equals(FS5)) + newValue = FS1; + } else if (oldValue instanceof com.sun.star.awt.Gradient) { + com.sun.star.awt.Gradient _newValue = copyStruct( + (com.sun.star.awt.Gradient) oldValue); + _newValue.Angle += 10; + _newValue.Border += 1; + _newValue.EndColor += 1000; + _newValue.EndIntensity -= 10; + _newValue.StartColor += 500; + _newValue.StartIntensity += 10; + _newValue.StepCount += 50; + _newValue.Style = com.sun.star.awt.GradientStyle.RADIAL; + _newValue.XOffset += 10; + _newValue.YOffset += 10; + newValue = _newValue; + } else if (oldValue instanceof com.sun.star.text.GraphicCrop) { + com.sun.star.text.GraphicCrop _newValue = copyStruct( + (com.sun.star.text.GraphicCrop) oldValue); + _newValue.Bottom += 10; + _newValue.Left += 10; + _newValue.Right += 10; + _newValue.Top += 10; + newValue = _newValue; + } else if (oldValue instanceof com.sun.star.drawing.BitmapMode) { + com.sun.star.drawing.BitmapMode bm1 = com.sun.star.drawing.BitmapMode.NO_REPEAT; + com.sun.star.drawing.BitmapMode bm2 = com.sun.star.drawing.BitmapMode.REPEAT; + com.sun.star.drawing.BitmapMode bm3 = com.sun.star.drawing.BitmapMode.STRETCH; + if (oldValue.equals(bm1)) + newValue = bm2; + if (oldValue.equals(bm2)) + newValue = bm3; + if (oldValue.equals(bm3)) + newValue = bm1; + } else if (oldValue instanceof com.sun.star.drawing.TextAdjust) { + com.sun.star.drawing.TextAdjust TA1 = com.sun.star.drawing.TextAdjust.BLOCK; + com.sun.star.drawing.TextAdjust TA2 = com.sun.star.drawing.TextAdjust.CENTER; + com.sun.star.drawing.TextAdjust TA3 = com.sun.star.drawing.TextAdjust.LEFT; + com.sun.star.drawing.TextAdjust TA4 = com.sun.star.drawing.TextAdjust.RIGHT; + com.sun.star.drawing.TextAdjust TA5 = com.sun.star.drawing.TextAdjust.STRETCH; + if (oldValue.equals(TA1)) + newValue = TA2; + if (oldValue.equals(TA2)) + newValue = TA3; + if (oldValue.equals(TA3)) + newValue = TA4; + if (oldValue.equals(TA4)) + newValue = TA5; + if (oldValue.equals(TA5)) + newValue = TA1; + } else if (oldValue instanceof com.sun.star.drawing.TextFitToSizeType) { + com.sun.star.drawing.TextFitToSizeType TF1 = com.sun.star.drawing.TextFitToSizeType.ALLLINES; + com.sun.star.drawing.TextFitToSizeType TF2 = com.sun.star.drawing.TextFitToSizeType.NONE; + com.sun.star.drawing.TextFitToSizeType TF3 = com.sun.star.drawing.TextFitToSizeType.PROPORTIONAL; + com.sun.star.drawing.TextFitToSizeType TF4 = com.sun.star.drawing.TextFitToSizeType.AUTOFIT; + if (oldValue.equals(TF1)) + newValue = TF2; + if (oldValue.equals(TF2)) + newValue = TF3; + if (oldValue.equals(TF3)) + newValue = TF4; + if (oldValue.equals(TF4)) + newValue = TF1; + } else if (oldValue instanceof com.sun.star.drawing.TextAnimationKind) { + com.sun.star.drawing.TextAnimationKind AK1 = com.sun.star.drawing.TextAnimationKind.NONE; + com.sun.star.drawing.TextAnimationKind AK2 = com.sun.star.drawing.TextAnimationKind.SLIDE; + com.sun.star.drawing.TextAnimationKind AK3 = com.sun.star.drawing.TextAnimationKind.SCROLL; + com.sun.star.drawing.TextAnimationKind AK4 = com.sun.star.drawing.TextAnimationKind.BLINK; + com.sun.star.drawing.TextAnimationKind AK5 = com.sun.star.drawing.TextAnimationKind.ALTERNATE; + + if (oldValue.equals(AK1)) + newValue = AK2; + if (oldValue.equals(AK2)) + newValue = AK3; + if (oldValue.equals(AK3)) + newValue = AK4; + if (oldValue.equals(AK4)) + newValue = AK5; + if (oldValue.equals(AK5)) + newValue = AK1; + } else if (oldValue instanceof com.sun.star.drawing.TextAnimationDirection) { + com.sun.star.drawing.TextAnimationDirection AD1 = com.sun.star.drawing.TextAnimationDirection.LEFT; + com.sun.star.drawing.TextAnimationDirection AD2 = com.sun.star.drawing.TextAnimationDirection.RIGHT; + com.sun.star.drawing.TextAnimationDirection AD3 = com.sun.star.drawing.TextAnimationDirection.DOWN; + com.sun.star.drawing.TextAnimationDirection AD4 = com.sun.star.drawing.TextAnimationDirection.UP; + if (oldValue.equals(AD1)) + newValue = AD2; + if (oldValue.equals(AD2)) + newValue = AD3; + if (oldValue.equals(AD3)) + newValue = AD4; + if (oldValue.equals(AD4)) + newValue = AD1; + } else if (oldValue instanceof com.sun.star.drawing.LineStyle) { + com.sun.star.drawing.LineStyle LS1 = com.sun.star.drawing.LineStyle.NONE; + com.sun.star.drawing.LineStyle LS2 = com.sun.star.drawing.LineStyle.DASH; + com.sun.star.drawing.LineStyle LS3 = com.sun.star.drawing.LineStyle.SOLID; + if (oldValue.equals(LS1)) + newValue = LS2; + if (oldValue.equals(LS2)) + newValue = LS3; + if (oldValue.equals(LS3)) + newValue = LS1; + } else if (oldValue instanceof com.sun.star.drawing.LineJoint) { + com.sun.star.drawing.LineJoint LJ1 = com.sun.star.drawing.LineJoint.BEVEL; + com.sun.star.drawing.LineJoint LJ2 = com.sun.star.drawing.LineJoint.MIDDLE; + com.sun.star.drawing.LineJoint LJ3 = com.sun.star.drawing.LineJoint.MITER; + com.sun.star.drawing.LineJoint LJ4 = com.sun.star.drawing.LineJoint.NONE; + com.sun.star.drawing.LineJoint LJ5 = com.sun.star.drawing.LineJoint.ROUND; + if (oldValue.equals(LJ1)) + newValue = LJ2; + if (oldValue.equals(LJ2)) + newValue = LJ3; + if (oldValue.equals(LJ3)) + newValue = LJ4; + if (oldValue.equals(LJ4)) + newValue = LJ5; + if (oldValue.equals(LJ5)) + newValue = LJ1; + } else if (oldValue instanceof com.sun.star.drawing.LineDash) { + com.sun.star.drawing.LineDash _newValue = copyStruct( + (com.sun.star.drawing.LineDash) oldValue); + _newValue.Dashes += 1; + _newValue.DashLen += 10; + _newValue.Distance += 20; + _newValue.DotLen += 10; + _newValue.Dots += 10; + _newValue.Style = com.sun.star.drawing.DashStyle.RECT; + newValue = _newValue; + } else if (oldValue instanceof com.sun.star.drawing.Hatch) { + com.sun.star.drawing.Hatch _newValue = copyStruct( + (com.sun.star.drawing.Hatch) oldValue); + _newValue.Angle += 10; + _newValue.Color += 1000; + _newValue.Distance += 10; + _newValue.Style = com.sun.star.drawing.HatchStyle.DOUBLE; + } else if (oldValue instanceof com.sun.star.drawing.RectanglePoint) { + com.sun.star.drawing.RectanglePoint RP1 = com.sun.star.drawing.RectanglePoint.LEFT_BOTTOM; + com.sun.star.drawing.RectanglePoint RP2 = com.sun.star.drawing.RectanglePoint.LEFT_MIDDLE; + com.sun.star.drawing.RectanglePoint RP3 = com.sun.star.drawing.RectanglePoint.LEFT_TOP; + com.sun.star.drawing.RectanglePoint RP4 = com.sun.star.drawing.RectanglePoint.MIDDLE_BOTTOM; + com.sun.star.drawing.RectanglePoint RP5 = com.sun.star.drawing.RectanglePoint.MIDDLE_MIDDLE; + com.sun.star.drawing.RectanglePoint RP6 = com.sun.star.drawing.RectanglePoint.MIDDLE_TOP; + com.sun.star.drawing.RectanglePoint RP7 = com.sun.star.drawing.RectanglePoint.RIGHT_BOTTOM; + com.sun.star.drawing.RectanglePoint RP8 = com.sun.star.drawing.RectanglePoint.RIGHT_MIDDLE; + com.sun.star.drawing.RectanglePoint RP9 = com.sun.star.drawing.RectanglePoint.RIGHT_TOP; + + if (oldValue.equals(RP1)) + newValue = RP2; + if (oldValue.equals(RP2)) + newValue = RP3; + if (oldValue.equals(RP3)) + newValue = RP4; + if (oldValue.equals(RP4)) + newValue = RP5; + if (oldValue.equals(RP5)) + newValue = RP6; + if (oldValue.equals(RP6)) + newValue = RP7; + if (oldValue.equals(RP7)) + newValue = RP8; + if (oldValue.equals(RP8)) + newValue = RP9; + if (oldValue.equals(RP9)) + newValue = RP1; + + } else if (oldValue instanceof com.sun.star.chart.ChartErrorCategory) { + com.sun.star.chart.ChartErrorCategory CC1 = com.sun.star.chart.ChartErrorCategory.CONSTANT_VALUE; + com.sun.star.chart.ChartErrorCategory CC2 = com.sun.star.chart.ChartErrorCategory.ERROR_MARGIN; + com.sun.star.chart.ChartErrorCategory CC3 = com.sun.star.chart.ChartErrorCategory.NONE; + com.sun.star.chart.ChartErrorCategory CC4 = com.sun.star.chart.ChartErrorCategory.PERCENT; + com.sun.star.chart.ChartErrorCategory CC5 = com.sun.star.chart.ChartErrorCategory.STANDARD_DEVIATION; + com.sun.star.chart.ChartErrorCategory CC6 = com.sun.star.chart.ChartErrorCategory.VARIANCE; + if (oldValue.equals(CC1)) + newValue = CC2; + if (oldValue.equals(CC2)) + newValue = CC3; + if (oldValue.equals(CC3)) + newValue = CC4; + if (oldValue.equals(CC4)) + newValue = CC5; + if (oldValue.equals(CC5)) + newValue = CC6; + if (oldValue.equals(CC6)) + newValue = CC1; + } else if (oldValue instanceof com.sun.star.chart.ChartErrorIndicatorType) { + com.sun.star.chart.ChartErrorIndicatorType IT1 = com.sun.star.chart.ChartErrorIndicatorType.LOWER; + com.sun.star.chart.ChartErrorIndicatorType IT2 = com.sun.star.chart.ChartErrorIndicatorType.NONE; + com.sun.star.chart.ChartErrorIndicatorType IT3 = com.sun.star.chart.ChartErrorIndicatorType.TOP_AND_BOTTOM; + com.sun.star.chart.ChartErrorIndicatorType IT4 = com.sun.star.chart.ChartErrorIndicatorType.UPPER; + if (oldValue.equals(IT1)) + newValue = IT2; + if (oldValue.equals(IT2)) + newValue = IT3; + if (oldValue.equals(IT3)) + newValue = IT4; + if (oldValue.equals(IT4)) + newValue = IT1; + } else if (oldValue instanceof com.sun.star.chart.ChartRegressionCurveType) { + com.sun.star.chart.ChartRegressionCurveType CT1 = com.sun.star.chart.ChartRegressionCurveType.EXPONENTIAL; + com.sun.star.chart.ChartRegressionCurveType CT2 = com.sun.star.chart.ChartRegressionCurveType.LINEAR; + com.sun.star.chart.ChartRegressionCurveType CT3 = com.sun.star.chart.ChartRegressionCurveType.LOGARITHM; + com.sun.star.chart.ChartRegressionCurveType CT4 = com.sun.star.chart.ChartRegressionCurveType.NONE; + com.sun.star.chart.ChartRegressionCurveType CT5 = com.sun.star.chart.ChartRegressionCurveType.POLYNOMIAL; + com.sun.star.chart.ChartRegressionCurveType CT6 = com.sun.star.chart.ChartRegressionCurveType.POWER; + if (oldValue.equals(CT1)) + newValue = CT2; + if (oldValue.equals(CT2)) + newValue = CT3; + if (oldValue.equals(CT3)) + newValue = CT4; + if (oldValue.equals(CT4)) + newValue = CT5; + if (oldValue.equals(CT5)) + newValue = CT6; + if (oldValue.equals(CT6)) + newValue = CT1; + + } else if (oldValue instanceof com.sun.star.chart.ChartDataRowSource) { + com.sun.star.chart.ChartDataRowSource RS1 = com.sun.star.chart.ChartDataRowSource.COLUMNS; + com.sun.star.chart.ChartDataRowSource RS2 = com.sun.star.chart.ChartDataRowSource.ROWS; + if (oldValue.equals(RS1)) + newValue = RS2; + if (oldValue.equals(RS2)) + newValue = RS1; + } else if (oldValue instanceof com.sun.star.awt.FontDescriptor) { + com.sun.star.awt.FontDescriptor _newValue = copyStruct( + (com.sun.star.awt.FontDescriptor) oldValue); + _newValue.CharacterWidth += 5; + _newValue.CharSet = com.sun.star.awt.CharSet.ANSI; + _newValue.Family = com.sun.star.awt.FontFamily.DECORATIVE; + _newValue.Height += 2; + _newValue.Kerning = !_newValue.Kerning; + _newValue.Name = "Courier"; + _newValue.Orientation += 45; + _newValue.Pitch = com.sun.star.awt.FontPitch.VARIABLE; + _newValue.Slant = com.sun.star.awt.FontSlant.REVERSE_ITALIC; + _newValue.Strikeout = com.sun.star.awt.FontStrikeout.X; + _newValue.StyleName = "Bold"; + _newValue.Type = com.sun.star.awt.FontType.SCALABLE; + _newValue.Underline = com.sun.star.awt.FontUnderline.BOLDDASHDOTDOT; + _newValue.Weight += 5; + _newValue.Width += 6; + _newValue.WordLineMode = !_newValue.WordLineMode; + + newValue = _newValue; + } else if (oldValue instanceof com.sun.star.form.NavigationBarMode) { + com.sun.star.form.NavigationBarMode BM1 = com.sun.star.form.NavigationBarMode.CURRENT; + com.sun.star.form.NavigationBarMode BM2 = com.sun.star.form.NavigationBarMode.NONE; + com.sun.star.form.NavigationBarMode BM3 = com.sun.star.form.NavigationBarMode.PARENT; + if (oldValue.equals(BM1)) + newValue = BM2; + if (oldValue.equals(BM2)) + newValue = BM3; + if (oldValue.equals(BM3)) + newValue = BM1; + } else if (oldValue instanceof com.sun.star.form.FormSubmitEncoding) { + com.sun.star.form.FormSubmitEncoding SE1 = com.sun.star.form.FormSubmitEncoding.MULTIPART; + com.sun.star.form.FormSubmitEncoding SE2 = com.sun.star.form.FormSubmitEncoding.TEXT; + com.sun.star.form.FormSubmitEncoding SE3 = com.sun.star.form.FormSubmitEncoding.URL; + if (oldValue.equals(SE1)) + newValue = SE2; + if (oldValue.equals(SE2)) + newValue = SE3; + if (oldValue.equals(SE3)) + newValue = SE1; + } else if (oldValue instanceof com.sun.star.form.FormSubmitMethod) { + com.sun.star.form.FormSubmitMethod FM1 = com.sun.star.form.FormSubmitMethod.GET; + com.sun.star.form.FormSubmitMethod FM2 = com.sun.star.form.FormSubmitMethod.POST; + if (oldValue.equals(FM1)) + newValue = FM2; + if (oldValue.equals(FM2)) + newValue = FM1; + } else if (oldValue instanceof com.sun.star.text.SectionFileLink) { + com.sun.star.text.SectionFileLink _newValue = new com.sun.star.text.SectionFileLink(); + + _newValue.FileURL = util.utils.getFullTestURL("SwXTextSection.sdw"); + newValue = _newValue; + } else if (oldValue instanceof com.sun.star.table.BorderLine) { + com.sun.star.table.BorderLine _newValue = copyStruct( + (com.sun.star.table.BorderLine) oldValue); + _newValue.Color += 2; + _newValue.InnerLineWidth += 2; + _newValue.LineDistance += 2; + _newValue.OuterLineWidth += 3; + if (_newValue instanceof com.sun.star.table.BorderLine2) { + ((com.sun.star.table.BorderLine2) _newValue).LineStyle + = com.sun.star.table.BorderLineStyle.DOUBLE; + } + newValue = _newValue; + } else if (oldValue instanceof com.sun.star.text.XTextColumns) { + com.sun.star.text.XTextColumns _newValue = (com.sun.star.text.XTextColumns) oldValue; + _newValue.setColumnCount((short) 1); + newValue = _newValue; + } else if (oldValue instanceof com.sun.star.form.FormButtonType) { + com.sun.star.form.FormButtonType BT1 = com.sun.star.form.FormButtonType.PUSH; + com.sun.star.form.FormButtonType BT2 = com.sun.star.form.FormButtonType.RESET; + com.sun.star.form.FormButtonType BT3 = com.sun.star.form.FormButtonType.SUBMIT; + com.sun.star.form.FormButtonType BT4 = com.sun.star.form.FormButtonType.URL; + + if (oldValue.equals(BT1)) + newValue = BT2; + if (oldValue.equals(BT2)) + newValue = BT3; + if (oldValue.equals(BT3)) + newValue = BT4; + if (oldValue.equals(BT4)) + newValue = BT1; + + } else if (oldValue instanceof com.sun.star.form.ListSourceType) { + com.sun.star.form.ListSourceType ST1 = com.sun.star.form.ListSourceType.QUERY; + com.sun.star.form.ListSourceType ST2 = com.sun.star.form.ListSourceType.SQL; + com.sun.star.form.ListSourceType ST3 = com.sun.star.form.ListSourceType.SQLPASSTHROUGH; + com.sun.star.form.ListSourceType ST4 = com.sun.star.form.ListSourceType.TABLE; + com.sun.star.form.ListSourceType ST5 = com.sun.star.form.ListSourceType.TABLEFIELDS; + com.sun.star.form.ListSourceType ST6 = com.sun.star.form.ListSourceType.VALUELIST; + if (oldValue.equals(ST1)) + newValue = ST2; + if (oldValue.equals(ST2)) + newValue = ST3; + if (oldValue.equals(ST3)) + newValue = ST4; + if (oldValue.equals(ST4)) + newValue = ST5; + if (oldValue.equals(ST5)) + newValue = ST6; + if (oldValue.equals(ST6)) + newValue = ST1; + } else if (oldValue instanceof com.sun.star.sheet.DataPilotFieldOrientation) { + com.sun.star.sheet.DataPilotFieldOrientation FO1 = com.sun.star.sheet.DataPilotFieldOrientation.PAGE; + com.sun.star.sheet.DataPilotFieldOrientation FO2 = com.sun.star.sheet.DataPilotFieldOrientation.COLUMN; + com.sun.star.sheet.DataPilotFieldOrientation FO3 = com.sun.star.sheet.DataPilotFieldOrientation.DATA; + com.sun.star.sheet.DataPilotFieldOrientation FO4 = com.sun.star.sheet.DataPilotFieldOrientation.HIDDEN; + com.sun.star.sheet.DataPilotFieldOrientation FO5 = com.sun.star.sheet.DataPilotFieldOrientation.ROW; + if (oldValue.equals(FO1)) + newValue = FO2; + if (oldValue.equals(FO2)) + newValue = FO3; + if (oldValue.equals(FO3)) + newValue = FO4; + if (oldValue.equals(FO4)) + newValue = FO5; + if (oldValue.equals(FO5)) + newValue = FO1; + } else if (oldValue instanceof com.sun.star.sheet.GeneralFunction) { + com.sun.star.sheet.GeneralFunction GF1 = com.sun.star.sheet.GeneralFunction.NONE; + com.sun.star.sheet.GeneralFunction GF2 = com.sun.star.sheet.GeneralFunction.AVERAGE; + com.sun.star.sheet.GeneralFunction GF3 = com.sun.star.sheet.GeneralFunction.COUNT; + com.sun.star.sheet.GeneralFunction GF4 = com.sun.star.sheet.GeneralFunction.COUNTNUMS; + com.sun.star.sheet.GeneralFunction GF5 = com.sun.star.sheet.GeneralFunction.MAX; + com.sun.star.sheet.GeneralFunction GF6 = com.sun.star.sheet.GeneralFunction.MIN; + com.sun.star.sheet.GeneralFunction GF7 = com.sun.star.sheet.GeneralFunction.AUTO; + com.sun.star.sheet.GeneralFunction GF8 = com.sun.star.sheet.GeneralFunction.PRODUCT; + com.sun.star.sheet.GeneralFunction GF9 = com.sun.star.sheet.GeneralFunction.STDEV; + com.sun.star.sheet.GeneralFunction GF10 = com.sun.star.sheet.GeneralFunction.STDEVP; + com.sun.star.sheet.GeneralFunction GF11 = com.sun.star.sheet.GeneralFunction.SUM; + com.sun.star.sheet.GeneralFunction GF12 = com.sun.star.sheet.GeneralFunction.VAR; + com.sun.star.sheet.GeneralFunction GF13 = com.sun.star.sheet.GeneralFunction.VARP; + + if (oldValue.equals(GF1)) + newValue = GF2; + if (oldValue.equals(GF2)) + newValue = GF3; + if (oldValue.equals(GF3)) + newValue = GF4; + if (oldValue.equals(GF4)) + newValue = GF5; + if (oldValue.equals(GF5)) + newValue = GF6; + if (oldValue.equals(GF6)) + newValue = GF7; + if (oldValue.equals(GF7)) + newValue = GF8; + if (oldValue.equals(GF8)) + newValue = GF9; + if (oldValue.equals(GF9)) + newValue = GF10; + if (oldValue.equals(GF10)) + newValue = GF11; + if (oldValue.equals(GF11)) + newValue = GF12; + if (oldValue.equals(GF12)) + newValue = GF13; + if (oldValue.equals(GF13)) + newValue = GF1; + } else if (oldValue instanceof com.sun.star.table.CellAddress) { + com.sun.star.table.CellAddress _newValue = copyStruct( + (com.sun.star.table.CellAddress) oldValue); + _newValue.Column += 1; + _newValue.Row += 1; + newValue = _newValue; + } else if (oldValue instanceof com.sun.star.table.TableOrientation) { + com.sun.star.table.TableOrientation TO1 = com.sun.star.table.TableOrientation.COLUMNS; + com.sun.star.table.TableOrientation TO2 = com.sun.star.table.TableOrientation.ROWS; + if (oldValue.equals(TO1)) + newValue = TO2; + else + newValue = TO1; + } else if (oldValue instanceof com.sun.star.sheet.DataImportMode) { + com.sun.star.sheet.DataImportMode DIM1 = com.sun.star.sheet.DataImportMode.NONE; + com.sun.star.sheet.DataImportMode DIM2 = com.sun.star.sheet.DataImportMode.QUERY; + com.sun.star.sheet.DataImportMode DIM3 = com.sun.star.sheet.DataImportMode.SQL; + com.sun.star.sheet.DataImportMode DIM4 = com.sun.star.sheet.DataImportMode.TABLE; + + if (oldValue.equals(DIM1)) + newValue = DIM2; + if (oldValue.equals(DIM2)) + newValue = DIM3; + if (oldValue.equals(DIM3)) + newValue = DIM4; + if (oldValue.equals(DIM4)) + newValue = DIM1; + + } else if (oldValue instanceof com.sun.star.style.BreakType) { + com.sun.star.style.BreakType BT1 = com.sun.star.style.BreakType.COLUMN_AFTER; + com.sun.star.style.BreakType BT2 = com.sun.star.style.BreakType.COLUMN_BEFORE; + com.sun.star.style.BreakType BT3 = com.sun.star.style.BreakType.COLUMN_BOTH; + com.sun.star.style.BreakType BT4 = com.sun.star.style.BreakType.PAGE_AFTER; + com.sun.star.style.BreakType BT5 = com.sun.star.style.BreakType.PAGE_BEFORE; + com.sun.star.style.BreakType BT6 = com.sun.star.style.BreakType.PAGE_BOTH; + com.sun.star.style.BreakType BT7 = com.sun.star.style.BreakType.NONE; + if (oldValue.equals(BT1)) + newValue = BT2; + if (oldValue.equals(BT2)) + newValue = BT3; + if (oldValue.equals(BT3)) + newValue = BT4; + if (oldValue.equals(BT4)) + newValue = BT5; + if (oldValue.equals(BT5)) + newValue = BT6; + if (oldValue.equals(BT6)) + newValue = BT7; + if (oldValue.equals(BT7)) + newValue = BT1; + } else if (oldValue instanceof PropertyValue) { + PropertyValue newVal = new PropertyValue(); + newVal.Name = ((PropertyValue) oldValue).Name; + newVal.Value = changePValue(((PropertyValue) oldValue).Value); + newValue = newVal; + } else if (oldValue instanceof com.sun.star.sheet.ValidationAlertStyle) { + com.sun.star.sheet.ValidationAlertStyle VAS1 = com.sun.star.sheet.ValidationAlertStyle.INFO; + com.sun.star.sheet.ValidationAlertStyle VAS2 = com.sun.star.sheet.ValidationAlertStyle.MACRO; + com.sun.star.sheet.ValidationAlertStyle VAS3 = com.sun.star.sheet.ValidationAlertStyle.STOP; + com.sun.star.sheet.ValidationAlertStyle VAS4 = com.sun.star.sheet.ValidationAlertStyle.WARNING; + + if (oldValue.equals(VAS1)) + newValue = VAS2; + if (oldValue.equals(VAS2)) + newValue = VAS3; + if (oldValue.equals(VAS3)) + newValue = VAS4; + if (oldValue.equals(VAS4)) + newValue = VAS1; + + } else if (oldValue instanceof com.sun.star.sheet.ValidationType) { + com.sun.star.sheet.ValidationType VT1 = com.sun.star.sheet.ValidationType.ANY; + com.sun.star.sheet.ValidationType VT2 = com.sun.star.sheet.ValidationType.CUSTOM; + com.sun.star.sheet.ValidationType VT3 = com.sun.star.sheet.ValidationType.DATE; + com.sun.star.sheet.ValidationType VT4 = com.sun.star.sheet.ValidationType.DECIMAL; + com.sun.star.sheet.ValidationType VT5 = com.sun.star.sheet.ValidationType.LIST; + com.sun.star.sheet.ValidationType VT6 = com.sun.star.sheet.ValidationType.TEXT_LEN; + com.sun.star.sheet.ValidationType VT7 = com.sun.star.sheet.ValidationType.TIME; + com.sun.star.sheet.ValidationType VT8 = com.sun.star.sheet.ValidationType.WHOLE; + + if (oldValue.equals(VT1)) + newValue = VT2; + if (oldValue.equals(VT2)) + newValue = VT3; + if (oldValue.equals(VT3)) + newValue = VT4; + if (oldValue.equals(VT4)) + newValue = VT5; + if (oldValue.equals(VT5)) + newValue = VT6; + if (oldValue.equals(VT6)) + newValue = VT7; + if (oldValue.equals(VT7)) + newValue = VT8; + if (oldValue.equals(VT8)) + newValue = VT1; + + } else if (oldValue instanceof com.sun.star.text.WritingMode) { + if (oldValue.equals(com.sun.star.text.WritingMode.LR_TB)) { + newValue = com.sun.star.text.WritingMode.TB_RL; + } else { + newValue = com.sun.star.text.WritingMode.LR_TB; + } + } else if (oldValue instanceof com.sun.star.uno.Enum) { + // universal changer for Enumerations + try { + Class<?> enumClass = oldValue.getClass(); + Field[] flds = enumClass.getFields(); + + for (int i = 0; i < flds.length; i++) { + if (Enum.class.equals(flds[i].getType().getSuperclass())) { + + Enum value = (Enum) flds[i].get(null); + if (!value.equals(oldValue)) { + newValue = value; + break; + } + } + } + } catch (Exception e) { + System.err + .println("Exception occurred while changing Enumeration value:"); + e.printStackTrace(System.err); + } + if (newValue == null) + newValue = oldValue; + + } else if (oldValue instanceof com.sun.star.style.TabStop[]) { + com.sun.star.style.TabStop[] old = (com.sun.star.style.TabStop[]) + oldValue; + com.sun.star.style.TabStop[] _newValue + = new com.sun.star.style.TabStop[old.length]; + for (int i = 0; i != old.length; ++i) { + _newValue[i] = copyStruct(old[i]); + } + if (_newValue.length == 0) { + _newValue = new com.sun.star.style.TabStop[1]; + } + com.sun.star.style.TabStop sep = new com.sun.star.style.TabStop(); + sep.Position += 1; + _newValue[0] = sep; + newValue = _newValue; + } else if (oldValue instanceof short[]) { + short[] oldArr = (short[]) oldValue; + int len = oldArr.length; + short[] newArr = new short[len + 1]; + for (int i = 0; i < len; i++) { + newArr[i] = (short) (oldArr[i] + 1); + } + newArr[len] = 5; + newValue = newArr; + } else if (oldValue instanceof String[]) { + String[] oldArr = (String[]) oldValue; + int len = oldArr.length; + String[] newArr = new String[len + 1]; + for (int i = 0; i < len; i++) { + newArr[i] = "_" + oldArr[i]; + } + newArr[len] = "_dummy"; + newValue = newArr; + } else if (oldValue instanceof PropertyValue) { + PropertyValue newVal = new PropertyValue(); + newVal.Name = ((PropertyValue) oldValue).Name; + newVal.Value = changePValue(((PropertyValue) oldValue).Value); + newValue = newVal; + } else if (oldValue instanceof com.sun.star.util.Date) { + com.sun.star.util.Date oldD = (com.sun.star.util.Date) oldValue; + com.sun.star.util.Date newD = new com.sun.star.util.Date(); + newD.Day = (short) (oldD.Day + (short) 1); + newValue = newD; + } else if (oldValue instanceof com.sun.star.util.DateTime) { + com.sun.star.util.DateTime oldDT = (com.sun.star.util.DateTime) oldValue; + com.sun.star.util.DateTime newDT = new com.sun.star.util.DateTime(); + newDT.Day = (short) (oldDT.Day + (short) 1); + newDT.Hours = (short) (oldDT.Hours + (short) 1); + newValue = newDT; + } else if (oldValue instanceof com.sun.star.util.Time) { + com.sun.star.util.Time oldT = (com.sun.star.util.Time) oldValue; + com.sun.star.util.Time newT = new com.sun.star.util.Time(); + newT.Hours = (short) (oldT.Hours + (short) 1); + newValue = newT; + } else if (oldValue instanceof com.sun.star.text.TableColumnSeparator) { + com.sun.star.text.TableColumnSeparator oldTCS = (com.sun.star.text.TableColumnSeparator) oldValue; + com.sun.star.text.TableColumnSeparator newTCS = new com.sun.star.text.TableColumnSeparator(); + newTCS.IsVisible = oldTCS.IsVisible; + newTCS.Position = (short) (oldTCS.Position - 1); + newValue = newTCS; + } else if (oldValue instanceof com.sun.star.drawing.HomogenMatrix3) { + com.sun.star.drawing.HomogenMatrix3 oldHM = (com.sun.star.drawing.HomogenMatrix3) oldValue; + com.sun.star.drawing.HomogenMatrix3 newHM = new com.sun.star.drawing.HomogenMatrix3(); + newHM.Line1.Column1 = oldHM.Line1.Column1 + 1; + newHM.Line2.Column2 = oldHM.Line2.Column2 + 1; + newHM.Line3.Column3 = oldHM.Line3.Column3 + 1; + newValue = newHM; + } else if (oldValue instanceof com.sun.star.drawing.PolyPolygonBezierCoords) { + com.sun.star.drawing.PolyPolygonBezierCoords oldPPC = (com.sun.star.drawing.PolyPolygonBezierCoords) oldValue; + com.sun.star.drawing.PolyPolygonBezierCoords newPPC = new com.sun.star.drawing.PolyPolygonBezierCoords(); + newPPC.Coordinates = oldPPC.Coordinates; + newPPC.Flags = oldPPC.Flags; + PolygonFlags[][] fArray = new PolygonFlags[1][1]; + PolygonFlags[] flags = new PolygonFlags[1]; + flags[0] = PolygonFlags.NORMAL; + fArray[0] = flags; + Point[][] pArray = new Point[1][1]; + Point[] points = new Point[1]; + Point aPoint = new Point(); + aPoint.X = 1; + aPoint.Y = 2; + points[0] = aPoint; + pArray[0] = points; + if (oldPPC.Coordinates.length == 0) { + newPPC.Coordinates = pArray; + newPPC.Flags = fArray; + } else { + if (oldPPC.Coordinates[0].length == 0) { + newPPC.Coordinates = pArray; + newPPC.Flags = fArray; + } else { + newPPC.Coordinates[0][0].X = oldPPC.Coordinates[0][0].X + 1; + newPPC.Coordinates[0][0].Y = oldPPC.Coordinates[0][0].Y + 1; + } + } + newValue = newPPC; + } else if (oldValue.getClass().isArray()) { + // changer for arrays : changes all elements + Class<?> arrType = oldValue.getClass().getComponentType(); + int oldLen = Array.getLength(oldValue); + if (oldLen == 0 && "TypedItemList".equals(name) && !arrType.isPrimitive()) { + // This case is needed to make the Sequence<Any> property pass + // the addPropertyChangeListener tests, where the property has + // to be changed (and not stay empty ...) + newValue = Array.newInstance(arrType, 1); + Object elem = new Any(new Type(String.class), "_Any"); + Array.set(newValue, 0, elem); + } else { + newValue = Array.newInstance(arrType, oldLen); + for (int i = 0; i < Array.getLength(newValue); i++) { + if (!arrType.isPrimitive()) { + Object elem = changePValue(Array.get(oldValue, i)); + Array.set(newValue, i, elem); + } else { + if (Boolean.TYPE.equals(arrType)) { + Array.setBoolean(newValue, i, + !Array.getBoolean(oldValue, i)); + } else if (Byte.TYPE.equals(arrType)) { + Array.setByte(newValue, i, + (byte) (Array.getByte(oldValue, i) + 1)); + } else if (Character.TYPE.equals(arrType)) { + Array.setChar(newValue, i, + (char) (Array.getChar(oldValue, i) + 1)); + } else if (Double.TYPE.equals(arrType)) { + Array.setDouble(newValue, i, + Array.getDouble(oldValue, i) + 1); + } else if (Float.TYPE.equals(arrType)) { + Array.setFloat(newValue, i, + Array.getFloat(oldValue, i) + 1); + } else if (Integer.TYPE.equals(arrType)) { + Array.setInt(newValue, i, Array.getInt(oldValue, i) + 1); + } else if (Long.TYPE.equals(arrType)) { + Array.setLong(newValue, i, + Array.getLong(oldValue, i) + 1); + } else if (Short.TYPE.equals(arrType)) { + Array.setShort(newValue, i, + (short) (Array.getShort(oldValue, i) + 1)); + } + } + } + } + } else if (isStructure(oldValue)) { + // universal changer for structures + Class<?> clazz = oldValue.getClass(); + try { + newValue = clazz.newInstance(); + Field[] fields = clazz.getFields(); + for (int i = 0; i < fields.length; i++) { + if ((fields[i].getModifiers() & Modifier.STATIC) == 0) { + Class<?> fType = fields[i].getType(); + Field field = fields[i]; + if (!fType.isPrimitive()) { + field.set(newValue, + changePValue(field.get(oldValue))); + } else { + if (Boolean.TYPE.equals(fType)) { + field.setBoolean(newValue, + !field.getBoolean(oldValue)); + } else if (Byte.TYPE.equals(fType)) { + field.setByte(newValue, + (byte) (field.getByte(oldValue) + 1)); + } else if (Character.TYPE.equals(fType)) { + field.setChar(newValue, + (char) (field.getChar(oldValue) + 1)); + } else if (Double.TYPE.equals(fType)) { + field.setDouble(newValue, + field.getDouble(oldValue) + 1); + } else if (Float.TYPE.equals(fType)) { + field.setFloat(newValue, + field.getFloat(oldValue) + 1); + } else if (Integer.TYPE.equals(fType)) { + field.setInt(newValue, + field.getInt(oldValue) + 1); + } else if (Long.TYPE.equals(fType)) { + field.setLong(newValue, + field.getLong(oldValue) + 1); + } else if (Short.TYPE.equals(fType)) { + field.setShort(newValue, + (short) (field.getShort(oldValue) + 1)); + } + } + } + } + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InstantiationException e) { + e.printStackTrace(); + } + + } else { + System.out.println("ValueChanger don't know type " + + oldValue.getClass()); + } + + return newValue; + + } // end of Change PValue + + public static Object changePValue(Object oldValue) { + return changePValue(oldValue, null); + } + + /** + * Checks if the passed value is the API structure. The value assumed to be + * a structure if there are no public methods, and all public fields are not + * static or final. + * + * @param val + * the value to be checked. + * @return <code>true</code> if the value is assumed to be a structure. + */ + public static boolean isStructure(Object val) { + boolean result = true; + + Class<?> clazz = val.getClass(); + + Method[] meth = clazz.getDeclaredMethods(); + for (int i = 0; i < meth.length; i++) { + result &= (meth[i].getModifiers() & Modifier.PUBLIC) == 0; + } + + Field[] fields = clazz.getDeclaredFields(); + for (int i = 0; i < fields.length; i++) { + int mod = fields[i].getModifiers(); + if (mod == (Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL) + && fields[i].getName().equals("UNOTYPEINFO")) + { + continue; + } + // If the field is PUBLIC it must not be STATIC or FINAL + result &= ((mod & Modifier.PUBLIC) == 0) + || (((mod & Modifier.STATIC) == 0) && ((mod & Modifier.FINAL) == 0)); + } + + return result; + } + + private static <T> T copyStruct(T value) { + Class<T> clazz = (Class<T>) value.getClass(); + T newValue; + try { + newValue = clazz.newInstance(); + } catch (IllegalAccessException e) { + throw new RuntimeException("unexpected " + e, e); + } catch (InstantiationException e) { + throw new RuntimeException("unexpected " + e, e); + } + Field[] fields = clazz.getFields(); + for (int i = 0; i != fields.length; ++i) { + if ((fields[i].getModifiers() & Modifier.STATIC) == 0) { + try { + fields[i].set(newValue, fields[i].get(value)); + } catch (IllegalAccessException e) { + throw new RuntimeException("unexpected " + e, e); + } + } + } + return newValue; + } +} diff --git a/qadevOOo/runner/util/ValueComparer.java b/qadevOOo/runner/util/ValueComparer.java new file mode 100644 index 000000000..a581ad3cb --- /dev/null +++ b/qadevOOo/runner/util/ValueComparer.java @@ -0,0 +1,231 @@ +/* + * 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 util; + +import com.sun.star.beans.PropertyValue; +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import com.sun.star.uno.Type; +import com.sun.star.uno.Enum; +import com.sun.star.uno.XInterface; +import com.sun.star.uno.Any; +import com.sun.star.uno.AnyConverter; +import java.util.HashMap; + + +public class ValueComparer { + + // Method to change a Value, thought for properties + public static boolean equalValue( Object first, Object second ) { + + if (first instanceof com.sun.star.uno.Any) { + try { + first = AnyConverter.toObject(((Any) first).getType(),first); + } catch (com.sun.star.lang.IllegalArgumentException iae) { + } + } + if (second instanceof com.sun.star.uno.Any) { + try { + second = AnyConverter.toObject(((Any) second).getType(),second); + } catch (com.sun.star.lang.IllegalArgumentException iae) { + } + } + boolean eq = false; + try { + if ( (first==null) || (second == null) ) { + eq = (first == second); + } + else { + if ( util.utils.isVoid(first) && util.utils.isVoid(second) ) { + eq=true; + } else if ( util.utils.isVoid(first) || util.utils.isVoid(second) ) { + eq = (first == second); + } else { + eq = compareObjects(first, second); + } + } + } + catch (Exception e) { + System.out.println("Exception occurred while comparing Objects"); + e.printStackTrace(); + } + return eq; + } // end of equalValue + + private static boolean compareArrayOfPropertyValue(PropertyValue[] pv1, PropertyValue[] pv2){ + if ( pv1.length != pv2.length) { + return false; + } + HashMap<String, Object> hm1 = new HashMap<String, Object>(); + boolean result = true; + int i = 0; + + for (i = 0; i < pv1.length; i++){ + hm1.put(pv1[i].Name, pv1[i].Value); + } + + i = 0; + while (i < pv2.length && result) { + result &= equalValue(hm1.get(pv2[i].Name),pv2[i].Value); + i++; + } + return result; + } + + private static boolean compareArrays(Object op1, Object op2) throws Exception { + + if (op1 instanceof PropertyValue[] && op2 instanceof PropertyValue[]) { + return compareArrayOfPropertyValue((PropertyValue[])op1,(PropertyValue[])op2); + } + boolean result = true; + if((op1.getClass().getComponentType() == op2.getClass().getComponentType()) + && (Array.getLength(op1) == Array.getLength(op2))) + { + for(int i = 0; i < Array.getLength(op1); ++ i) + result = result & compareObjects(Array.get(op1, i), Array.get(op2, i)); + } else { + result = false ; + } + + return result; + } + + private static boolean compareInterfaces(XInterface op1, XInterface op2) { + return op1 == op2; + } + + private static boolean compareUntil(Class<?> zClass, Class<?> untilClass, Object op1, Object op2) throws Exception { + boolean result = true; + + // write inherited members first + Class<?> superClass = zClass.getSuperclass(); + if(superClass != null && superClass != untilClass) + result = result & compareUntil(superClass, untilClass, op1, op2); + + Field fields[] = zClass.getDeclaredFields(); + + for(int i = 0; i < fields.length && result; ++ i) { + if((fields[i].getModifiers() & (Modifier.STATIC | Modifier.TRANSIENT)) == 0) { // neither static nor transient ? + Object obj1 = fields[i].get(op1); + Object obj2 = fields[i].get(op2); + if (obj1 instanceof com.sun.star.uno.Any) { + try { + if (utils.isVoid(obj1)) { + obj1 = null; + } else { + obj1 = AnyConverter.toObject(((Any) obj1).getType(),obj1); + } + } catch (com.sun.star.lang.IllegalArgumentException iae) { + } + } + if (obj2 instanceof com.sun.star.uno.Any) { + try { + if (utils.isVoid(obj2)) { + obj2 = null; + } else { + obj2 = AnyConverter.toObject(((Any) obj2).getType(),obj2); + } + } catch (com.sun.star.lang.IllegalArgumentException iae) { + } + } + + result = result & compareObjects(obj1, obj2); + + } + } + + return result; + } + + private static boolean compareStructs(Object op1, Object op2) throws Exception { + boolean result = true; + + if(op1.getClass() != op2.getClass()) + result = false; + else { + result = compareUntil(op1.getClass(), Object.class, op1, op2); + } + + return result; + } + + private static boolean compareThrowable(Throwable op1, Throwable op2) throws Exception { + boolean result = true; + + if(op1.getClass() != op2.getClass()) + result = false; + else { + result = compareUntil(op1.getClass(), Throwable.class, op1, op2); + + result = result & op1.getMessage().equals(op2.getMessage()); + } + + return result; + } + + private static boolean compareEnums(Enum en1, Enum en2) { + return en1.getValue() == en2.getValue(); + } + + private static boolean compareObjects(Object op1, Object op2) throws Exception { + if(op1 == op2) + return true; + else if(op1==null || op2 == null) + return op1 == op2; + else if(op1.getClass().isPrimitive() && op2.getClass().isPrimitive()) + return op1.equals(op2); + else if(op1.getClass() == Byte.class && op2.getClass() == Byte.class) + return op1.equals(op2); + else if(op1.getClass() == Type.class && op2.getClass() == Type.class) + return op1.equals(op2); + else if(op1.getClass() == Boolean.class && op2.getClass() == Boolean.class) + return op1.equals(op2); + else if(op1.getClass() == Short.class && op2.getClass() == Short.class) + return op1.equals(op2); + else if(Throwable.class.isAssignableFrom(op1.getClass()) && Throwable.class.isAssignableFrom(op2.getClass())) + return compareThrowable((Throwable)op1, (Throwable)op2); + else if(op1.getClass() == Integer.class && op2.getClass() == Integer.class) + return op1.equals(op2); + else if(op1.getClass() == Character.class && op2.getClass() == Character.class) + return op1.equals(op2); + else if(op1.getClass() == Long.class && op2.getClass() == Long.class) + return op1.equals(op2); + else if(op1.getClass() == Void.class && op2.getClass() == Void.class) + return op1.equals(op2); + else if(op1.getClass() == Float.class && op2.getClass() == Float.class) + return op1.equals(op2); + else if(op1.getClass() == Double.class && op2.getClass() == Double.class) + return op1.equals(op2); + else if(op1.getClass().isArray() && op2.getClass().isArray()) + return compareArrays(op1, op2); + else if(op1.getClass() == Void.class || op2.getClass() == void.class) // write nothing ? + return true; + else if(XInterface.class.isAssignableFrom(op1.getClass()) && XInterface.class.isAssignableFrom(op2.getClass())) + return compareInterfaces((XInterface)op1, (XInterface)op2); + else if(Enum.class.isAssignableFrom(op1.getClass()) && Enum.class.isAssignableFrom(op2.getClass())) + return compareEnums((Enum)op1, (Enum)op2); + else if(op1.getClass() == String.class && op2.getClass() == String.class) // is it a String ? + return ((String)op1).equals(op2); + else // otherwise it must be a struct + return compareStructs(op1, op2); + } + + +} diff --git a/qadevOOo/runner/util/WaitUnreachable.java b/qadevOOo/runner/util/WaitUnreachable.java new file mode 100644 index 000000000..f90fa6552 --- /dev/null +++ b/qadevOOo/runner/util/WaitUnreachable.java @@ -0,0 +1,119 @@ +/* + * 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 util; + +import java.lang.ref.PhantomReference; +import java.lang.ref.ReferenceQueue; + +/** + * Wait until an object has become unreachable. + * + * <p>Instances of this class will typically be used as either:</p> + * <pre> + * SomeType o = new SomeType(...); + * ... // use "o" + * WaitUnreachable u = new WaitUnreachable(o); + * o = null; + * u.waitUnreachable(); + * </pre> + * <p>or:</p> + * <pre> + * WaitUnreachable u = new WaitUnreachable(new SomeType(...)); + * ... // use "(SomeType) u.get()" + * u.waitUnreachable(); + * </pre> + */ +public final class WaitUnreachable { + /** + * Creates a new waiter. + * + * @param obj the object on which to wait + */ + public WaitUnreachable(Object obj) { + this.obj = obj; + queue = new ReferenceQueue<Object>(); + ref = new PhantomReference<Object>(obj, queue); + } + + /** + * Gets the object on which to wait. + * + * @return the object on which to wait, or <code>null</code> if + * <code>waitUnreachable</code> has already been called + */ + public synchronized Object get() { + return obj; + } + + /** + * Starts waiting for the object to become unreachable. + * + * <p>This blocks the current thread until the object has become + * unreachable.</p> + * + * <p>Actually, this method waits until the JVM has <em>detected</em> that + * the object has become unreachable. This is not deterministic, but this + * methods makes a best effort to cause the JVM to eventually detect the + * situation. With a typical JVM, this should suffice.</p> + */ + public void waitUnreachable() { + synchronized (this) { + obj = null; + } + System.out.println("waiting for gc"); + while (queue.poll() == null) { + System.gc(); + System.runFinalization(); + } + } + + /** + * Ensures that an object will be finalized as soon as possible. + * + * <p>This does not block the current thread. Instead, a new thread is + * spawned that busy waits for the given object to become unreachable.</p> + * + * <p>This method cannot guarantee that the given object is eventually + * finalized, but it makes a best effort. With a typical JVM, this should + * suffice.</p> + * + * @param obj the object of which to ensure finalization + */ + public static void ensureFinalization(final Object obj) { + final class WaitThread extends Thread { + private WaitThread(Object obj) { + super("ensureFinalization"); + unreachable = new WaitUnreachable(obj); + } + + @Override + public void run() { + unreachable.waitUnreachable(); + } + + private final WaitUnreachable unreachable; + } + new WaitThread(obj).start(); + } + + private Object obj; + private final ReferenceQueue<Object> queue; + @SuppressWarnings("unused") + private final PhantomReference<Object> ref; +} diff --git a/qadevOOo/runner/util/WriterTools.java b/qadevOOo/runner/util/WriterTools.java new file mode 100644 index 000000000..cdff65557 --- /dev/null +++ b/qadevOOo/runner/util/WriterTools.java @@ -0,0 +1,128 @@ +/* + * 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 util; + +import com.sun.star.beans.PropertyValue; +import com.sun.star.beans.XPropertySet; + +import com.sun.star.container.XNamed; + +import com.sun.star.drawing.XDrawPage; +import com.sun.star.drawing.XDrawPageSupplier; + +import com.sun.star.lang.XComponent; +import com.sun.star.lang.XMultiServiceFactory; + +import com.sun.star.text.XText; +import com.sun.star.text.XTextContent; +import com.sun.star.text.XTextCursor; +import com.sun.star.text.XTextDocument; + +import com.sun.star.graphic.XGraphic; +import com.sun.star.graphic.XGraphicProvider; + +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; + +public class WriterTools { + public static XTextDocument createTextDoc(XMultiServiceFactory xMSF) { + PropertyValue[] Args = new PropertyValue[0]; + XComponent comp = DesktopTools.openNewDoc(xMSF, "swriter", Args); + XTextDocument WriterDoc = UnoRuntime.queryInterface( + XTextDocument.class, comp); + + return WriterDoc; + } // finish createTextDoc + + public static XTextDocument loadTextDoc(XMultiServiceFactory xMSF, + String url) { + PropertyValue[] Args = new PropertyValue[0]; + XTextDocument WriterDoc = loadTextDoc(xMSF, url, Args); + + return WriterDoc; + } // finish createTextDoc + + private static XTextDocument loadTextDoc(XMultiServiceFactory xMSF, + String url, PropertyValue[] Args) { + XComponent comp = DesktopTools.loadDoc(xMSF, url, Args); + XTextDocument WriterDoc = UnoRuntime.queryInterface( + XTextDocument.class, comp); + + return WriterDoc; + } // finish createTextDoc + + public static XDrawPage getDrawPage(XTextDocument aDoc) { + XDrawPage oDP = null; + + try { + XDrawPageSupplier oDPS = UnoRuntime.queryInterface( + XDrawPageSupplier.class, aDoc); + oDP = oDPS.getDrawPage(); + } catch (Exception e) { + throw new IllegalArgumentException("Couldn't get drawpage", e); + } + + return oDP; + } + + public static void insertTextGraphic(XTextDocument aDoc, + XMultiServiceFactory xMSF, XComponentContext xContext, int hpos, + int vpos, int width, int height, + String pic, String name) { + try { + Object oGObject = xMSF.createInstance( + "com.sun.star.text.GraphicObject"); + + XGraphicProvider xGraphicProvider = UnoRuntime.queryInterface( + XGraphicProvider.class, + xContext.getServiceManager().createInstanceWithContext( + "com.sun.star.graphic.GraphicProvider", xContext)); + + String fullURL = util.utils.getFullTestURL(pic); + + PropertyValue[] aMediaProps = new PropertyValue[] { new PropertyValue() }; + aMediaProps[0].Name = "URL"; + aMediaProps[0].Value = fullURL; + + XGraphic xGraphic = UnoRuntime.queryInterface(XGraphic.class, + xGraphicProvider.queryGraphic(aMediaProps)); + + XText the_text = aDoc.getText(); + XTextCursor the_cursor = the_text.createTextCursor(); + XTextContent the_content = UnoRuntime.queryInterface( + XTextContent.class, oGObject); + the_text.insertTextContent(the_cursor, the_content, true); + + XPropertySet oProps = UnoRuntime.queryInterface( + XPropertySet.class, oGObject); + + oProps.setPropertyValue("Graphic", xGraphic); + oProps.setPropertyValue("HoriOrientPosition", Integer.valueOf(hpos)); + oProps.setPropertyValue("VertOrientPosition", Integer.valueOf(vpos)); + oProps.setPropertyValue("Width", Integer.valueOf(width)); + oProps.setPropertyValue("Height", Integer.valueOf(height)); + + XNamed the_name = UnoRuntime.queryInterface(XNamed.class, + oGObject); + the_name.setName(name); + } catch (Exception ex) { + System.out.println("Exception while inserting TextGraphic"); + ex.printStackTrace(); + } + } +} diff --git a/qadevOOo/runner/util/XInstCreator.java b/qadevOOo/runner/util/XInstCreator.java new file mode 100644 index 000000000..c0fe76837 --- /dev/null +++ b/qadevOOo/runner/util/XInstCreator.java @@ -0,0 +1,29 @@ +/* + * 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 util; + +import com.sun.star.uno.XInterface; +import com.sun.star.container.XIndexAccess; + +public interface XInstCreator { + + XInterface getInstance(); + XInterface createInstance(); + XIndexAccess getCollection(); +} diff --git a/qadevOOo/runner/util/XLayerHandlerImpl.java b/qadevOOo/runner/util/XLayerHandlerImpl.java new file mode 100644 index 000000000..399db9a24 --- /dev/null +++ b/qadevOOo/runner/util/XLayerHandlerImpl.java @@ -0,0 +1,110 @@ +/* + * 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 util; + +public class XLayerHandlerImpl + implements com.sun.star.configuration.backend.XLayerHandler { + private String calls = ""; + private final String ls = System.getProperty("line.separator"); + + public void addOrReplaceNode(String str, short param) + throws com.sun.star.configuration.backend.MalformedDataException, + com.sun.star.lang.WrappedTargetException { + calls += ("addOrReplace(" + str + "," + param + ");" + ls); + } + + public void addOrReplaceNodeFromTemplate(String str, + com.sun.star.configuration.backend.TemplateIdentifier templateIdentifier, + short param) + throws com.sun.star.configuration.backend.MalformedDataException, + com.sun.star.lang.WrappedTargetException { + calls += ("addOrReplaceNodeFromTemplate(" + str + "," + templateIdentifier + ");" + ls); + } + + public void addProperty(String str, short param, + com.sun.star.uno.Type type) + throws com.sun.star.configuration.backend.MalformedDataException, + com.sun.star.lang.WrappedTargetException { + calls += ("addProperty(" + str + "," + param + "," + type + ");" + ls); + } + + public void addPropertyWithValue(String str, short param, Object obj) + throws com.sun.star.configuration.backend.MalformedDataException, + com.sun.star.lang.WrappedTargetException { + calls += ("addPropertyWithValue(" + str + "," + param + "," + obj + ");" + ls); + } + + public void dropNode(String str) + throws com.sun.star.configuration.backend.MalformedDataException, + com.sun.star.lang.WrappedTargetException { + calls += ("dropNode(" + str + ");" + ls); + } + + public void endLayer() + throws com.sun.star.configuration.backend.MalformedDataException, + com.sun.star.lang.WrappedTargetException { + calls += ("endLayer();" + ls); + } + + public void endNode() + throws com.sun.star.configuration.backend.MalformedDataException, + com.sun.star.lang.WrappedTargetException { + calls += ("endNode();" + ls); + } + + public void endProperty() + throws com.sun.star.configuration.backend.MalformedDataException, + com.sun.star.lang.WrappedTargetException { + calls += ("endProperty();" + ls); + } + + public void overrideNode(String str, short param, boolean param2) + throws com.sun.star.configuration.backend.MalformedDataException, + com.sun.star.lang.WrappedTargetException { + calls += ("overrideNode(" + str + "," + param + "," + param2 + ");" + ls); + } + + public void overrideProperty(String str, short param, + com.sun.star.uno.Type type, boolean param3) + throws com.sun.star.configuration.backend.MalformedDataException, + com.sun.star.lang.WrappedTargetException { + calls += ("overrideProperty(" + str + "," + param + "," + type + "," + param3 + ");" + ls); + } + + public void setPropertyValue(Object obj) + throws com.sun.star.configuration.backend.MalformedDataException, + com.sun.star.lang.WrappedTargetException { + calls += ("setPropertyValue(" + obj + ");" + ls); + } + + public void setPropertyValueForLocale(Object obj, String str) + throws com.sun.star.configuration.backend.MalformedDataException, + com.sun.star.lang.WrappedTargetException { + calls += ("setPropertyValueForLocale(" + obj + "," + str + ");" + ls); + } + + public void startLayer() + throws com.sun.star.configuration.backend.MalformedDataException, + com.sun.star.lang.WrappedTargetException { + calls = "startLayer();" + ls; + } + + public String getCalls() { + return calls; + } +}
\ No newline at end of file diff --git a/qadevOOo/runner/util/XLayerImpl.java b/qadevOOo/runner/util/XLayerImpl.java new file mode 100644 index 000000000..3b2ac9ca4 --- /dev/null +++ b/qadevOOo/runner/util/XLayerImpl.java @@ -0,0 +1,33 @@ +/* + * 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 util; + +public class XLayerImpl implements com.sun.star.configuration.backend.XLayer { + + private boolean wasCalled = false; + + public void readData(com.sun.star.configuration.backend.XLayerHandler xLayerHandler) throws com.sun.star.lang.NullPointerException, com.sun.star.lang.WrappedTargetException, com.sun.star.configuration.backend.MalformedDataException { + wasCalled = true; + } + + public boolean hasBeenCalled() { + return wasCalled; + } + +} diff --git a/qadevOOo/runner/util/XMLTools.java b/qadevOOo/runner/util/XMLTools.java new file mode 100644 index 000000000..fc821b9ff --- /dev/null +++ b/qadevOOo/runner/util/XMLTools.java @@ -0,0 +1,669 @@ +/* + * 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 util; + +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; + +import com.sun.star.beans.PropertyValue; +import com.sun.star.xml.sax.XAttributeList; +import com.sun.star.xml.sax.XDocumentHandler; +import com.sun.star.xml.sax.XLocator; + + +public class XMLTools { + + /** + * The implementation of <code>com.sun.star.xml.sax.XAttributeList</code> + * where attributes and their values can be added. + */ + public static class AttributeList implements XAttributeList { + private static class Attribute { + public String Name ; + public String Type ; + public String Value ; + } + private final HashMap<String, Attribute> attrByName = new HashMap<String, Attribute>() ; + private final ArrayList<Attribute> attributes = new ArrayList<Attribute>() ; + + /** + * Creates a class instance. + */ + public AttributeList() {} + + private AttributeList(XAttributeList list) { + if (list == null) return ; + for (short i = 0; i < list.getLength(); i++) { + add(list.getNameByIndex(i), list.getTypeByIndex(i), + list.getValueByIndex(i)) ; + } + } + + /** + * Adds an attribute with type and value specified. + * @param name The attribute name. + * @param type Value type (usually 'CDATA' used). + * @param value Attribute value. + */ + public void add(String name, String type, String value) { + Attribute attr = new Attribute() ; + attr.Name = name ; + attr.Type = type ; + attr.Value = value ; + attributes.add(attr) ; + attrByName.put(attr.Name, attr) ; + } + + + + + + /*************************************** + * XAttributeList methods + ****************************************/ + + public short getLength() { + return (short) attributes.size() ; + } + + public String getNameByIndex(short idx) { + String name = attributes.get(idx).Name ; + return name ; + } + + public String getTypeByIndex(short idx) { + String type = attributes.get(idx).Type ; + return type; + } + + public String getTypeByName(String name) { + String type = attrByName.get(name).Type ; + return type; + } + public String getValueByIndex(short idx) { + String value = attributes.get(idx).Value ; + return value; + } + + public String getValueByName(String name) { + String value = attrByName.get(name).Value ; + return value; + } + } + + /** + * This class writes all XML data handled into a stream specified + * in the constructor. + */ + private static class XMLWriter implements XDocumentHandler { + private PrintWriter _log = null ; + private String align = "" ; + + /** + * Creates a SAX handler which writes all XML data + * handled into a <code>log</code> stream specified. + */ + private XMLWriter(PrintWriter log) { + _log = log ; + } + + /** + * Creates a SAX handler which does nothing. + */ + public XMLWriter() { + } + + public void processingInstruction(String appl, String data) { + if (_log == null) return ; + _log.println(align + "<?" + appl + " " + data + "?>") ; + } + public void startDocument() { + if (_log == null) return ; + _log.println("START DOCUMENT:") ; + } + public void endDocument() { + if (_log == null) return ; + _log.println("END DOCUMENT:") ; + } + public void setDocumentLocator(XLocator loc) { + if (_log == null) return ; + _log.println("DOCUMENT LOCATOR: ('" + loc.getPublicId() + + "','" + loc.getSystemId() + "')") ; + } + public void startElement(String name, XAttributeList attr) { + if (_log == null) return ; + _log.print(align + "<" + name + " ") ; + if (attr != null) { + short attrLen = attr.getLength() ; + for (short i = 0; i < attrLen; i++) { + if (i != 0) _log.print(align + " ") ; + _log.print(attr.getNameByIndex(i) + "[" + + attr.getTypeByIndex(i) + "]=\"" + + attr.getValueByIndex(i) + "\"") ; + if (i+1 != attrLen) { + _log.println() ; + } + } + } + _log.println(">") ; + + align += " " ; + } + + public void endElement(String name) { + if (_log == null) return ; + align = align.substring(3) ; + _log.println(align + "</" + name + ">") ; + } + + public void characters(String chars) { + if (_log == null) return ; + _log.println(align + chars) ; + } + public void ignorableWhitespace(String sp) { + if (_log == null) return ; + _log.println(sp) ; + } + } + + /** + * Checks if the XML structure is well formed (i.e. all tags opened must be + * closed and all tags opened inside a tag must be closed + * inside the same tag). It also checks parameters passed. + * If any collisions found appropriate error message is + * output into a stream specified. No XML data output, i.e. + * no output will be performed if no errors occur.<p> + * After document is completed there is a way to check + * if the XML data and structure was valid. + */ + private static class XMLWellFormChecker extends XMLWriter { + private boolean docStarted = false ; + private boolean docEnded = false ; + ArrayList<String> tagStack = new ArrayList<String>() ; + private boolean wellFormed = true ; + private boolean noOtherErrors = true ; + PrintWriter log = null ; + private boolean printXMLData = false ; + + private XMLWellFormChecker(PrintWriter log) { + super() ; + this.log = log ; + } + + private XMLWellFormChecker(PrintWriter log_, boolean printXMLData) { + super(printXMLData ? log_ : null) ; + this.printXMLData = printXMLData ; + this.log = log_ ; + } + + /** + * Reset all values. This is important e.g. for test of XFilter + * interface, where 'filter()' method is started twice. + */ + void reset() { + docStarted = false ; + docEnded = false ; + tagStack = new ArrayList<String>() ; + wellFormed = true ; + noOtherErrors = true ; + printXMLData = false ; + } + + @Override + public void startDocument() { + super.startDocument(); + + if (docStarted) { + printError("Document is started twice.") ; + wellFormed = false ; + } + + docStarted = true ; + } + @Override + public void endDocument() { + super.endDocument(); + if (!docStarted) { + wellFormed = false ; + printError("Document ended but not started.") ; + } + docEnded = true ; + } + @Override + public void startElement(String name, XAttributeList attr) { + super.startElement(name, attr); + if (attr == null) { + printError("attribute list passed as parameter to startElement()"+ + " method has null value for tag <" + name + ">") ; + noOtherErrors = false ; + } + tagStack.add(0, name) ; + } + @Override + public void endElement(String name) { + super.endElement(name); + if (wellFormed) { + if (tagStack.isEmpty()) { + wellFormed = false ; + printError("No tags to close (bad closing tag </" + name + ">)") ; + } else { + String startTag = tagStack.get(0) ; + tagStack.remove(0) ; + if (!startTag.equals(name)) { + wellFormed = false ; + printError("Bad closing tag: </" + name + + ">; tag expected: </" + startTag + ">"); + } + } + } + } + + /** + * Checks if there were no errors during document handling. + * I.e. startDocument() and endDocument() must be called, + * XML must be well formed, parameters must be valid. + */ + public boolean isWellFormed() { + if (!docEnded) { + printError("Document was not ended.") ; + wellFormed = false ; + } + + return wellFormed && noOtherErrors ; + } + + /** + * Prints error message and all tags where error occurred inside. + * Also prints "Tag trace" in case if the full XML data isn't + * printed. + */ + void printError(String msg) { + log.println("!!! Error: " + msg) ; + if (printXMLData) return ; + log.println(" Tag trace :") ; + for (int i = 0; i < tagStack.size(); i++) { + String tag = tagStack.get(i) ; + log.println(" <" + tag + ">") ; + } + } + } + + /** + * Beside structure of XML this class also can check existence + * of tags, inner tags, and character data. After document + * completion there is a way to check if required tags and + * character data was found. If there any error occurs an + * appropriate message is output. + */ + public static class XMLTagsChecker extends XMLWellFormChecker { + private final HashMap<String,String> tags = new HashMap<String,String>() ; + private final HashMap<String,String> chars = new HashMap<String,String>() ; + private boolean allOK = true ; + + public XMLTagsChecker(PrintWriter log) { + super(log) ; + } + + /** + * Adds a tag name which must be contained in the XML data. + */ + public void addTag(String tag) { + tags.put(tag, "") ; + } + /** + * Adds a tag name which must be contained in the XML data and + * must be inside the tag with name <code>outerTag</code>. + */ + public void addTagEnclosed(String tag, String outerTag) { + tags.put(tag, outerTag) ; + } + + /** + * Adds a character data which must be contained in the XML data and + * must be inside the tag with name <code>outerTag</code>. + */ + public void addCharactersEnclosed(String ch, String outerTag) { + chars.put(ch, outerTag) ; + } + + @Override + public void startElement(String name, XAttributeList attrs) { + super.startElement(name, attrs) ; + if (tags.containsKey(name)) { + String outerTag = tags.get(name); + if (outerTag.length() != 0) { + boolean isInTag = false ; + for (int i = 0; i < tagStack.size(); i++) { + if (outerTag.equals(tagStack.get(i))) { + isInTag = true ; + break ; + } + } + if (!isInTag) { + printError("Required tag <" + name + "> found, but is not enclosed in tag <" + + outerTag + ">") ; + allOK = false ; + } + } + tags.remove(name) ; + } + } + + @Override + public void characters(String ch) { + super.characters(ch) ; + + if (chars.containsKey(ch)) { + String outerTag = chars.get(ch); + if (outerTag.length() != 0) { + boolean isInTag = false ; + for (int i = 0; i < tagStack.size(); i++) { + if (outerTag.equals(tagStack.get(i))) { + isInTag = true ; + break ; + } + } + if (!isInTag) { + printError("Required characters '" + ch + "' found, but are not enclosed in tag <" + + outerTag + ">") ; + allOK = false ; + } + } + chars.remove(ch) ; + } + } + + /** + * Checks if the XML data was valid and well formed and if + * all necessary tags and character data was found. + */ + public boolean checkTags() { + if (!isWellFormed()) + allOK = false ; + + Iterator<String> badTags = tags.keySet().iterator() ; + Iterator<String> badChars = chars.keySet().iterator() ; + + if (badTags.hasNext()) { + allOK = false ; + log.println("Required tags were not found in export :") ; + while(badTags.hasNext()) { + log.println(" <" + badTags.next() + ">") ; + } + } + if (badChars.hasNext()) { + allOK = false ; + log.println("Required characters were not found in export :") ; + while(badChars.hasNext()) { + log.println(" <" + badChars.next() + ">") ; + } + } + reset(); + return allOK ; + } + } + + /** + * Represents an XML tag which must be found in XML data written. + * This tag can contain only its name or tag name and attribute + * name, or attribute value additionally. + */ + public static class Tag { + private final String name; + private String[][] attrList = new String[0][3] ; + + /** + * Creates tag which has only a name. Attributes don't make sense. + * @param tagName The name of the tag. + */ + public Tag(String tagName) { + name = tagName ; + } + + /** + * Creates a tag with the name specified, which must have an + * attribute with the value specified. The type of value + * assumed to be 'CDATA'. + * @param tagName The name of the tag. + * @param attrName The name of attribute which must be contained + * in the tag. + * @param attrValue Attribute value. + */ + public Tag(String tagName, String attrName, String attrValue) { + name = tagName ; + attrList = new String[1][3] ; + attrList[0][0] = attrName ; + attrList[0][1] = "CDATA" ; + attrList[0][2] = attrValue ; + } + + /** + * Gets tag String description. + */ + @Override + public String toString() { + StringBuffer ret = new StringBuffer("<" + name); + for (int i = 0; i < attrList.length; i++) { + ret.append(" ").append(attrList[i][0]).append("="); + if (attrList[i][2] == null) { + ret.append("(not specified)"); + } else { + ret.append("\"").append(attrList[i][2]).append("\""); + } + } + ret.append(">"); + + return ret.toString(); + } + + private boolean checkAttr(int attrListIdx, XAttributeList list) { + short j = 0 ; + int listLen = list.getLength(); + while(j < listLen) { + if (attrList[attrListIdx][0].equals(list.getNameByIndex(j))) { + if (attrList[attrListIdx][2] == null) return true ; + return attrList[attrListIdx][2].equals(list.getValueByIndex(j)) ; + } + j++ ; + } + return false ; + } + + /** + * Checks if this tag matches tag passed in parameters. + * I.e. if tag specifies only its name it matches if names + * are equal (attributes don't make sense). If there are + * some attributes names specified in this tag method checks + * if all names present in attribute list <code>list</code> + * (attributes' values don't make sense). If attributes specified + * with values method checks if these attributes exist and + * have appropriate values. + */ + private boolean isMatchTo(String tagName, XAttributeList list) { + if (!name.equals(tagName)) return false; + boolean result = true ; + for (int i = 0; i < attrList.length; i++) { + result &= checkAttr(i, list) ; + } + return result ; + } + } + + /** + * Class realises extended XML data checking. It has possibilities + * to check if a tag exists, if it has some attributes with + * values, and if this tag is contained in another tag (which + * also can specify any attributes). It can check if some + * character data exists inside any tag specified. + */ + public static class XMLChecker extends XMLWellFormChecker { + private final HashSet<String> tagSet = new HashSet<String>() ; + private final ArrayList<Tag[]> tags = new ArrayList<Tag[]>() ; + private final ArrayList<Object[]> chars = new ArrayList<Object[]>() ; + private final ArrayList<String> tagStack = new ArrayList<String>() ; + private final ArrayList<AttributeList> attrStack = new ArrayList<AttributeList>() ; + + public XMLChecker(PrintWriter log, boolean writeXML) { + super(log, writeXML) ; + } + + public void addTag(Tag tag) { + tags.add(new Tag[] {tag, null}) ; + tagSet.add(tag.name) ; + } + + public void addTagEnclosed(Tag tag, Tag outerTag) { + tags.add(new Tag[] {tag, outerTag}) ; + tagSet.add(tag.name) ; + } + + + + public void addCharactersEnclosed(String ch, Tag outerTag) { + chars.add(new Object[] {ch.trim(), outerTag}) ; + } + + @Override + public void startElement(String name, XAttributeList attr) { + try { + super.startElement(name, attr); + + if (tagSet.contains(name)) { + for (int i = 0; i < tags.size(); i++) { + Tag[] tag = tags.get(i); + if (tag[0].isMatchTo(name, attr)) { + if (tag[1] == null) { + tags.remove(i--); + } else { + boolean isInStack = false ; + for (int j = 0; j < tagStack.size(); j++) { + if (tag[1].isMatchTo(tagStack.get(j), + attrStack.get(j))) { + + isInStack = true ; + break ; + } + } + if (isInStack) { + tags.remove(i--) ; + } + } + } + } + } + + tagStack.add(0, name) ; + attrStack.add(0, new AttributeList(attr)); + } catch (Exception e) { + e.printStackTrace(log); + } + } + + @Override + public void characters(String ch) { + super.characters(ch) ; + for (int i = 0; i < chars.size(); i++) { + Object[] chr = chars.get(i); + if (((String) chr[0]).equals(ch)) { + if (chr[1] == null) { + chars.remove(i--); + } else { + boolean isInStack = false ; + for (int j = 0; j < tagStack.size(); j++) { + if (((Tag) chr[1]).isMatchTo(tagStack.get(j), + attrStack.get(j))) { + + isInStack = true ; + break ; + } + } + if (isInStack) { + chars.remove(i--) ; + } + } + } + } + } + + @Override + public void endElement(String name) { + try { + super.endElement(name); + + if (tagStack.size() > 0) { + tagStack.remove(0) ; + attrStack.remove(0) ; + } + } catch(Exception e) { + e.printStackTrace(log) ; + } + } + + public boolean check() { + if (tags.size()> 0) { + log.println("!!! Error: Some tags were not found :") ; + for (int i = 0; i < tags.size(); i++) { + Tag[] tag = tags.get(i) ; + log.println(" Tag " + tag[0] + " was not found"); + if (tag[1] != null) + log.println(" inside tag " + tag[1]) ; + } + } + if (chars.size() > 0) { + log.println("!!! Error: Some character data blocks were not found :") ; + for (int i = 0; i < chars.size(); i++) { + Object[] ch = chars.get(i) ; + log.println(" Character data \"" + ch[0] + "\" was not found ") ; + if (ch[1] != null) + log.println(" inside tag " + ch[1]) ; + } + } + + if (!isWellFormed()) + log.println("!!! Some errors were found in XML structure") ; + + boolean result = tags.isEmpty() && chars.isEmpty() && isWellFormed(); + reset(); + return result; + } + } + + + + public static PropertyValue[] createMediaDescriptor(String[] propNames, Object[] values) { + PropertyValue[] props = new PropertyValue[propNames.length] ; + + for (int i = 0; i < props.length; i++) { + props[i] = new PropertyValue() ; + props[i].Name = propNames[i] ; + if (values != null && i < values.length) { + props[i].Value = values[i] ; + } + } + + return props ; + } + + + + +} diff --git a/qadevOOo/runner/util/XSchemaHandlerImpl.java b/qadevOOo/runner/util/XSchemaHandlerImpl.java new file mode 100644 index 000000000..cd72fd6ed --- /dev/null +++ b/qadevOOo/runner/util/XSchemaHandlerImpl.java @@ -0,0 +1,128 @@ +/* + * 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 util; + +public class XSchemaHandlerImpl + implements com.sun.star.configuration.backend.XSchemaHandler { + private String calls = ""; + private final String ls = System.getProperty("line.separator"); + + public void addInstance(String str, + com.sun.star.configuration.backend.TemplateIdentifier templateIdentifier) + throws com.sun.star.configuration.backend.MalformedDataException, + com.sun.star.lang.WrappedTargetException { + calls += ("addInstance();" + ls); + } + + public void addItemType(com.sun.star.configuration.backend.TemplateIdentifier templateIdentifier) + throws com.sun.star.configuration.backend.MalformedDataException, + com.sun.star.lang.WrappedTargetException { + calls += ("addItemType();" + ls); + } + + public void addProperty(String str, short param, + com.sun.star.uno.Type type) + throws com.sun.star.configuration.backend.MalformedDataException, + com.sun.star.lang.WrappedTargetException { + calls += ("addProperty();" + ls); + } + + public void addPropertyWithDefault(String str, short param, Object obj) + throws com.sun.star.configuration.backend.MalformedDataException, + com.sun.star.lang.WrappedTargetException { + calls += ("addPropertyWithDefault();" + ls); + } + + public void endComponent() + throws com.sun.star.configuration.backend.MalformedDataException, + com.sun.star.lang.WrappedTargetException { + calls += ("endComponent();" + ls); + } + + public void endNode() + throws com.sun.star.configuration.backend.MalformedDataException, + com.sun.star.lang.WrappedTargetException { + calls += ("endNode();" + ls); + } + + public void endSchema() + throws com.sun.star.configuration.backend.MalformedDataException, + com.sun.star.lang.WrappedTargetException { + calls += ("endSchema();" + ls); + } + + public void endTemplate() + throws com.sun.star.configuration.backend.MalformedDataException, + com.sun.star.lang.WrappedTargetException { + calls += ("endTemplate();" + ls); + } + + public void importComponent(String str) + throws com.sun.star.configuration.backend.MalformedDataException, + com.sun.star.lang.WrappedTargetException { + calls += ("importComponent();" + ls); + } + + public void startComponent(String str) + throws com.sun.star.configuration.backend.MalformedDataException, + com.sun.star.lang.WrappedTargetException { + calls += ("startComponent();" + ls); + } + + public void startGroup(String str, short param) + throws com.sun.star.configuration.backend.MalformedDataException, + com.sun.star.lang.WrappedTargetException { + calls += ("startGroup();" + ls); + } + + public void startGroupTemplate(com.sun.star.configuration.backend.TemplateIdentifier templateIdentifier, + short param) + throws com.sun.star.configuration.backend.MalformedDataException, + com.sun.star.lang.WrappedTargetException { + calls += ("startGroupTemplate();" + ls); + } + + public void startSchema() + throws com.sun.star.configuration.backend.MalformedDataException, + com.sun.star.lang.WrappedTargetException { + calls += ("startSchema();" + ls); + } + + public void startSet(String str, short param, + com.sun.star.configuration.backend.TemplateIdentifier templateIdentifier) + throws com.sun.star.configuration.backend.MalformedDataException, + com.sun.star.lang.WrappedTargetException { + calls += ("startSet();" + ls); + } + + public void startSetTemplate(com.sun.star.configuration.backend.TemplateIdentifier templateIdentifier, + short param, + com.sun.star.configuration.backend.TemplateIdentifier templateIdentifier2) + throws com.sun.star.configuration.backend.MalformedDataException, + com.sun.star.lang.WrappedTargetException { + calls += ("startSetTemplate();" + ls); + } + + public String getCalls() { + return calls; + } + + public void cleanCalls() { + calls = ""; + } +}
\ No newline at end of file diff --git a/qadevOOo/runner/util/db/DataSource.java b/qadevOOo/runner/util/db/DataSource.java new file mode 100644 index 000000000..b9f41c332 --- /dev/null +++ b/qadevOOo/runner/util/db/DataSource.java @@ -0,0 +1,146 @@ +/* + * 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 util.db; + +import com.sun.star.beans.XPropertySet; +import com.sun.star.container.NoSuchElementException; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.sdbc.XDataSource; +import com.sun.star.uno.Exception; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XNamingService; +import lib.StatusException; + +/** wraps a com.sun.star.sdb.DataSource + */ +public class DataSource +{ + protected DataSource( XMultiServiceFactory _orb, DataSourceDescriptor _descriptor ) + { + m_orb = _orb; + try + { + m_dataSource = UnoRuntime.queryInterface( XDataSource.class, + m_orb.createInstance( "com.sun.star.sdb.DataSource" ) ); + m_properties = UnoRuntime.queryInterface( XPropertySet.class, + m_dataSource ); + + Object[] descriptorProperties = new Object[] { + null, _descriptor.URL, _descriptor.Info, _descriptor.User, _descriptor.Password, + _descriptor.IsPasswordRequired }; + String[] propertyNames = new String[] { + "Name", "URL", "Info", "User", "Password", "IsPasswordRequired" }; + for ( int i=0; i < descriptorProperties.length; ++i ) + if ( descriptorProperties[i] != null ) + m_properties.setPropertyValue( propertyNames[i], descriptorProperties[i] ); + } + catch ( Exception e ) + { + throw new StatusException( "could not create/fill a css.sdb.DataSource object", e ); + } + } + + public XDataSource getDataSource() + { + return m_dataSource; + } + + /** + * retrieves the css.sdb.OfficeDatabaseDocument associated with the data source + */ + public synchronized DatabaseDocument getDatabaseDocument() + { + if ( m_document == null ) + m_document = new DatabaseDocument( this ); + return m_document; + } + + public void revokeRegistration() + { + String dataSourceName = ""; + try + { + dataSourceName = (String)m_properties.getPropertyValue( "Name" ); + XNamingService dbContext = UnoRuntime.queryInterface( XNamingService.class, + m_orb.createInstance( "com.sun.star.sdb.DatabaseContext" ) ); + dbContext.revokeObject( dataSourceName ); + } + catch ( Exception e ) + { + throw new StatusException( "DataSource.revokeRegistration: could not revoke the object (" + dataSourceName + ")", e ); + } + } + + public void registerAs( final String _registrationName, final boolean _revokeIfRegistered ) + { + String doing = null; + try + { + doing = "creating database context"; + XNamingService dbContext = UnoRuntime.queryInterface( XNamingService.class, + m_orb.createInstance( "com.sun.star.sdb.DatabaseContext" ) ); + + if ( _revokeIfRegistered ) + { + doing = "revoking previously registered data source"; + try + { + dbContext.revokeObject( _registrationName ); + } + catch( NoSuchElementException e ) + { /* allowed here */ } + } + + // if the document associated with the database document has not yet been saved, then we need to do so + DatabaseDocument doc = getDatabaseDocument(); + String docURL = doc.getURL(); + if ( docURL.length() == 0 ) + { + final java.io.File tempFile = java.io.File.createTempFile( _registrationName + "_", ".odb" ); + if ( tempFile.exists() ) { + // we did not really want to create that file, we just wanted its local name, but + // createTempFile actually creates it => throw it away + // (This is necessary since some JVM/platform combinations seem to actually lock the file) + boolean bDeleteOk = tempFile.delete(); + if (!bDeleteOk) { + System.out.println("delete failed"); + } + } + String localPart = tempFile.toURI().toURL().toString(); + localPart = localPart.substring( localPart.lastIndexOf( '/' ) + 1 ); + docURL = util.utils.getOfficeTemp( m_orb ) + localPart; + doing = "storing database document to temporary location (" + docURL + ")"; + doc.storeAsURL( docURL ); + } + + // register the data source + doing = "registering the data source at the database context"; + dbContext.registerObject( _registrationName, m_dataSource ); + } + catch( final java.lang.Exception e ) + { + throw new StatusException( "DataSource.registerAs: error during " + doing, e ); + } + } + + private final XMultiServiceFactory m_orb; + private final XDataSource m_dataSource; + private final XPropertySet m_properties; + private DatabaseDocument m_document = null; +} diff --git a/qadevOOo/runner/util/db/DataSourceDescriptor.java b/qadevOOo/runner/util/db/DataSourceDescriptor.java new file mode 100644 index 000000000..6b699445f --- /dev/null +++ b/qadevOOo/runner/util/db/DataSourceDescriptor.java @@ -0,0 +1,60 @@ +/* + * 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 util.db; + +import com.sun.star.beans.PropertyValue; +import com.sun.star.lang.XMultiServiceFactory; + +/** a descriptor for creating a com.sun.star.sdb.DataSource + */ +public class DataSourceDescriptor +{ + /** + * Representation of <code>'URL'</code> property. + */ + public String URL = null ; + /** + * Representation of <code>'Info'</code> property. + */ + public PropertyValue[] Info = null ; + /** + * Representation of <code>'User'</code> property. + */ + public String User = null ; + /** + * Representation of <code>'Password'</code> property. + */ + public String Password = null ; + /** + * Representation of <code>'IsPasswordRequired'</code> property. + */ + public Boolean IsPasswordRequired = null ; + + public DataSourceDescriptor( XMultiServiceFactory _orb ) + { + m_orb = _orb; + } + + public DataSource createDataSource() + { + return new DataSource( m_orb, this ); + } + + private final XMultiServiceFactory m_orb; +} diff --git a/qadevOOo/runner/util/db/DatabaseDocument.java b/qadevOOo/runner/util/db/DatabaseDocument.java new file mode 100644 index 000000000..f9c4913e7 --- /dev/null +++ b/qadevOOo/runner/util/db/DatabaseDocument.java @@ -0,0 +1,71 @@ +/* + * 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 util.db; + +import com.sun.star.beans.PropertyValue; +import com.sun.star.frame.XModel; +import com.sun.star.frame.XStorable; +import com.sun.star.io.IOException; +import com.sun.star.sdb.XDocumentDataSource; +import com.sun.star.sdb.XOfficeDatabaseDocument; +import com.sun.star.uno.UnoRuntime; + +/** + * encapsulates a css.sdb.DatabaseDocument + */ +public class DatabaseDocument +{ + protected DatabaseDocument( final DataSource _dataSource ) + { + XDocumentDataSource docDataSource = UnoRuntime.queryInterface( + XDocumentDataSource.class, _dataSource.getDataSource() ); + m_databaseDocument = UnoRuntime.queryInterface(XOfficeDatabaseDocument.class, + docDataSource.getDatabaseDocument() ); + + m_model = UnoRuntime.queryInterface( XModel.class, m_databaseDocument ); + m_storeDoc = UnoRuntime.queryInterface( XStorable.class, m_databaseDocument ); + } + + public XOfficeDatabaseDocument getDatabaseDocument() + { + return m_databaseDocument; + } + + /** + * passes through to XModel.getURL. + */ + public String getURL() + { + return m_model.getURL(); + } + + /** + * simplified version (taking no arguments except the target URL) of XStorage.storeAsURL + * @param _url + * specifies the location to where to store the document + */ + public void storeAsURL( final String _url ) throws IOException + { + m_storeDoc.storeAsURL( _url, new PropertyValue[] { } ); + } + + private final XOfficeDatabaseDocument m_databaseDocument; + private final XModel m_model; + private final XStorable m_storeDoc; +} diff --git a/qadevOOo/runner/util/dbg.java b/qadevOOo/runner/util/dbg.java new file mode 100644 index 000000000..5416e92f6 --- /dev/null +++ b/qadevOOo/runner/util/dbg.java @@ -0,0 +1,274 @@ +/* + * 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 util; + +import com.sun.star.uno.XInterface; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.Type; +import com.sun.star.beans.XPropertySet; +import com.sun.star.beans.XPropertySetInfo; +import com.sun.star.beans.Property; +import com.sun.star.beans.PropertyAttribute; +import com.sun.star.beans.PropertyValue; +import com.sun.star.lang.XTypeProvider; +import com.sun.star.lang.XServiceInfo; +import java.io.PrintWriter; +import java.io.OutputStreamWriter; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.Method; + +/** + * This class accumulates all kinds of methods for accessing debug information + * from UNO implementations. + */ +public class dbg { + + /** + * Prints information about the supported interfaces of an implementation + * to standard out. + * @param xTarget The implementation which should be analysed. + * @see com.sun.star.uno.XInterface + */ + public static void printInterfaces(XInterface xTarget) { + printInterfaces(xTarget, false); + } + + /** + * Prints information about the supported interfaces of an implementation + * to standard out. Extended information can be printed. + * @param xTarget The implementation which should be analysed. + * @param extendedInfo Should extended information be printed? + * @see com.sun.star.uno.XInterface + */ + private static void printInterfaces(XInterface xTarget, + boolean extendedInfo){ + Type[] types = getInterfaceTypes(xTarget); + if( null != types ) { + int nLen = types.length; + for( int i = 0; i < nLen ; i++ ) { + System.out.println(types[i].getTypeName()); + if (extendedInfo) { + printInterfaceInfo(types[i]); + System.out.println(); + } + } + } + } + + /** + * Returns all interface types of an implementation as a type array. + * @param xTarget The implementation which should be analyzed. + * @return An array with all interface types; null if there are none. + * @see com.sun.star.uno.XInterface + */ + private static Type[] getInterfaceTypes(XInterface xTarget) { + Type[] types = null; + XTypeProvider xTypeProvider = UnoRuntime.queryInterface( XTypeProvider.class, xTarget); + if( xTypeProvider != null ) + types = xTypeProvider.getTypes(); + return types; + } + + + + /** + * Prints information about an interface type. + * + * @param aType The type of the given interface. + * @see com.sun.star.uno.Type + */ + private static void printInterfaceInfo(Type aType) { + try { + Class<?> zClass = aType.getZClass(); + Method[] methods = zClass.getDeclaredMethods(); + for (int i=0; i<methods.length; i++) { + System.out.println("\t" + methods[i].getReturnType().getName() + + " " + methods[i].getName() + "()"); + } + } + catch (Exception ex) { + System.out.println("Exception occurred while printing InterfaceInfo"); + ex.printStackTrace(); + } + } + + /** + * Prints a string array to standard out. + * + * @param entries : The array to be printed. + */ + public static void printArray( String [] entries ) { + for ( int i=0; i< entries.length;i++ ) { + System.out.println(entries[i]); + } + } + + /** + * Print all information about the property <code>name</code> from + * the property set <code>PS</code> to standard out. + * @param PS The property set which should contain a property called + * <code>name</code>. + * @param name The name of the property. + * @see com.sun.star.beans.XPropertySet + */ + public static void printPropertyInfo(XPropertySet PS, String name) throws UnsupportedEncodingException { + printPropertyInfo(PS, name, new PrintWriter(new OutputStreamWriter(System.out, "UTF-8"))); + } + + /** + * Print all information about the property <code>name</code> from + * the property set <code>PS</code> to a print writer. + * @param PS The property set which should contain a property called + * <code>name</code>. + * @param name The name of the property. + * @param out The print writer which is used as output. + * @see com.sun.star.beans.XPropertySet + */ + public static void printPropertyInfo(XPropertySet PS, String name, + PrintWriter out) { + try { + XPropertySetInfo PSI = PS.getPropertySetInfo(); + PSI.getProperties(); + Property prop = PSI.getPropertyByName(name); + out.println("Property name is " + prop.Name); + out.println("Property handle is " + prop.Handle); + out.println("Property type is " + prop.Type.getTypeName()); + out.println("Property current value is " + + PS.getPropertyValue(name)); + out.println("Attributes :"); + short attr = prop.Attributes; + + if ((attr & PropertyAttribute.BOUND) != 0) + out.println("\t-BOUND"); + + if ((attr & PropertyAttribute.CONSTRAINED) != 0) + out.println("\t-CONSTRAINED"); + + if ((attr & PropertyAttribute.MAYBEAMBIGUOUS) != 0) + out.println("\t-MAYBEAMBIGUOUS"); + + if ((attr & PropertyAttribute.MAYBEDEFAULT) != 0) + out.println("\t-MAYBEDEFAULT"); + + if ((attr & PropertyAttribute.MAYBEVOID) != 0) + out.println("\t-MAYBEVOID"); + + if ((attr & PropertyAttribute.READONLY) != 0) + out.println("\t-READONLY"); + + if ((attr & PropertyAttribute.REMOVABLE) != 0) + out.println("\t-REMOVABLE"); + + if ((attr & PropertyAttribute.TRANSIENT) != 0) + out.println("\t-TRANSIENT"); + } catch(com.sun.star.uno.Exception e) { + out.println("Exception!!!!"); + e.printStackTrace(out); + } + } + + + + /** + * Print the names and the values of a sequence of <code>PropertyValue</code> + * to a print writer. + * @param ps The property which should displayed + * @param out The print writer which is used as output. + * @see com.sun.star.beans.PropertyValue + */ + private static void printPropertyValueSequencePairs(PropertyValue[] ps, PrintWriter out){ + for( int i = 0; i < ps.length; i++){ + printPropertyValuePairs(ps[i], out); + } + } + + + + /** + * Print the name and the value of a <code>PropertyValue</code> to a print writer. + * @param ps The property which should displayed + * @param out The print writer which is used as output. + * @see com.sun.star.beans.PropertyValue + */ + private static void printPropertyValuePairs(PropertyValue ps, PrintWriter out){ + + if (ps.Value instanceof String[] ){ + String[] values = (String[]) ps.Value; + StringBuilder oneValue = new StringBuilder("value is an empty String[]"); + if (values.length > 0){ + oneValue.append("['"); + for( int i=0; i < values.length; i++){ + oneValue.append(values[i]); + if (i+1 < values.length) oneValue.append("';'"); + } + oneValue.append("']"); + } + out.println("--------"); + out.println(" Name: '" + ps.Name + "' contains String[]:"); + out.println(oneValue.toString()); + out.println("--------"); + + } else if (ps.Value instanceof PropertyValue){ + out.println("--------"); + out.println(" Name: '" + ps.Name + "' contains PropertyValue:"); + printPropertyValuePairs((PropertyValue)ps.Value, out); + out.println("--------"); + + } else if (ps.Value instanceof PropertyValue[]){ + out.println("--------"); + out.println(" Name: '" + ps.Name + "' contains PropertyValue[]:"); + printPropertyValueSequencePairs((PropertyValue[])ps.Value, out); + out.println("--------"); + + } else { + out.println("Name: '" + ps.Name + "' Value: '" + ps.Value.toString() + "'"); + } + } + + /** + * Print the names of all properties inside this property set + * @param ps The property set which is printed. + * @see com.sun.star.beans.XPropertySet + */ + public static void printPropertiesNames(XPropertySet ps) { + XPropertySetInfo psi = ps.getPropertySetInfo(); + Property[] props = psi.getProperties(); + for (int i = 0; i < props.length; i++) + System.out.println(i + ". " + props[i].Name); + } + + /** + * Print the supported services of a UNO object. + * @param aObject A UNO object. + */ + public static void getSuppServices (Object aObject) { + XServiceInfo xSI = UnoRuntime.queryInterface(XServiceInfo.class,aObject); + printArray(xSI.getSupportedServiceNames()); + StringBuilder str = new StringBuilder("Therein not Supported Service"); + boolean notSupportedServices = false; + for (int i=0;i<xSI.getSupportedServiceNames().length;i++) { + if (! xSI.supportsService(xSI.getSupportedServiceNames()[i])) { + notSupportedServices = true; + str.append("\n").append(xSI.getSupportedServiceNames()[i]); + } + } + if (notSupportedServices) + System.out.println(str.toString()); + } +} diff --git a/qadevOOo/runner/util/utils.java b/qadevOOo/runner/util/utils.java new file mode 100644 index 000000000..1e6901fca --- /dev/null +++ b/qadevOOo/runner/util/utils.java @@ -0,0 +1,846 @@ +/* + * 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 util; + +import com.sun.star.frame.XController; +import com.sun.star.frame.XDispatch; +import com.sun.star.frame.XDispatchProvider; +import com.sun.star.frame.XModel; +import com.sun.star.lang.XComponent; + +import java.util.StringTokenizer; +import java.io.*; +import java.util.ArrayList; +import java.net.Socket; +import java.net.ServerSocket; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Arrays; + +import com.sun.star.awt.XToolkitExperimental; +import com.sun.star.beans.XPropertySet; +import com.sun.star.beans.Property; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.ucb.InteractiveAugmentedIOException; +import com.sun.star.ucb.XSimpleFileAccess; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.util.URL; +import com.sun.star.util.XURLTransformer; +import com.sun.star.uno.AnyConverter; +import com.sun.star.uno.Type; +import com.sun.star.uno.XComponentContext; +import com.sun.star.util.XMacroExpander; + +import java.text.DecimalFormat; +import java.util.Calendar; +import java.util.Collections; +import java.util.GregorianCalendar; + +public class utils { + + /** + * + * This method adds the DOCPTH to a given file + * + * @param sDocName the file which should be completed to the test doc path + * @return $TESTDOCPATH/sDocName + */ + public static String getFullTestDocName(String sDocName) { + String docpth = System.getProperty("DOCPTH"); + if (docpth.endsWith("\\") || docpth.endsWith("/")) { + docpth = docpth.substring(0, docpth.length() - 1); + } + + System.out.println("docpth:" + docpth); + + String pthSep = System.getProperty("file.separator"); + + if (docpth.equals("unknown")) { + System.out.println("try to get tDoc from $SRC_ROOT/qadevOOo"); + String srcRoot = System.getProperty(PropertyName.SRC_ROOT); + if (srcRoot != null) { + File srcR = new File(srcRoot); + String[] list = srcR.list(new FilenameFilter() { + + public boolean accept(File dir, String name) { + return name.startsWith("qadevOOo"); + } + }); + + if (list != null && list[0] != null) { + String tDoc = srcRoot.concat(pthSep).concat(list[0]).concat(pthSep).concat("testdocs"); + + if (new File(tDoc).exists()) { + docpth = tDoc; + } + } + } + } + + if (docpth.startsWith("http:")) { + return docpth + "/" + sDocName; + } + String testdocPth = ""; + + if (docpth.equals("unknown")) { + System.out.println("try to get tDoc from OBJDSCS"); + String objdscPth = System.getProperty("OBJDSCS"); + if (objdscPth != null) { + int i = objdscPth.indexOf("objdsc"); + String arcPth = objdscPth.substring(0, i - 1); + testdocPth = arcPth + pthSep + "doc" + pthSep + "java" + + pthSep + "testdocs" + pthSep + sDocName; + } + } else { + testdocPth = docpth + pthSep + sDocName; + } + return testdocPth; + } + + /** + * + * This method adds the DOCPTH to a given file + * and changes the format to an file URL + * + */ + public static String getFullTestURL(String sDocName) { + String fullDocPath = getFullTestDocName(sDocName); + if (fullDocPath.startsWith("http:")) { + return fullDocPath; + } + if (fullDocPath.startsWith("file:")) { + return fullDocPath; + } + String prefix = null; + + // Windows: \\\\margritte\\qaapi\\workspace\\qadev\\testdocs/emptyChart.sds + if (fullDocPath.startsWith("\\\\")) { + prefix = "file:"; + } + + fullDocPath = fullDocPath.replace('\\', '/'); + if (prefix == null) { + if (fullDocPath.startsWith("//")) { + prefix = "file:/"; + } else if (fullDocPath.startsWith("/")) { + prefix = "file://"; + } else { + prefix = "file:///"; + } + } + if (!fullDocPath.endsWith("/")) { + File aFile = new File(fullDocPath); + if (aFile.isDirectory()) { + fullDocPath += "/"; + } + } + String fulldocURL = prefix + fullDocPath; + return fulldocURL; + } + + /** + * + * This method changes a given URL to a valid file URL + * + */ + public static String getFullURL(String sDocName) { + String fullDocPath = sDocName; + fullDocPath = fullDocPath.replace('\\', '/'); + + if (fullDocPath.startsWith("http:")) { + return fullDocPath; + } + if (fullDocPath.startsWith("ftp:")) { + return fullDocPath; + } + String prefix = ""; + if (!fullDocPath.startsWith("file:///")) { + if (fullDocPath.startsWith("//")) { + prefix = "file:"; + } else { + if (fullDocPath.startsWith("/")) { + prefix = "file://"; + } + else + { + prefix = "file:///"; + } + } + } + if (!fullDocPath.endsWith("/")) { + File aFile = new File(fullDocPath); + if (aFile.isDirectory()) { + fullDocPath += "/"; + } + } + String fulldocURL = prefix + fullDocPath; + + return fulldocURL; + } + + /** + * + * This method gets the user dir of the connected office + * + */ + public static String getOfficeUserPath(XMultiServiceFactory msf) { + // get a folder located in the user dir + String userPath = getOfficeSettingsValue(msf, "UserConfig"); + + // strip the returned folder to the user dir + if (userPath.charAt(userPath.length() - 1) == '/') { + userPath = userPath.substring(0, userPath.length() - 1); + } + int index = userPath.lastIndexOf('/'); + if (index != -1) { + userPath = userPath.substring(0, index); + } + + return userPath; + } + + /** + * In the office there are some settings available. This function + * returns the value of the given setting name. For Example the setting name "Temp" + * "Temp" returns the temp folder of the office instance. + * @param msf a XMultiServiceFactory + * @param setting the name of the setting the value should be returned. + * For example "Temp" returns the temp folder of the current office instance. + * @see com.sun.star.util.PathSettings + * @return the value as String + */ + private static String getOfficeSettingsValue(XMultiServiceFactory msf, String setting) { + try { + Object settings = msf.createInstance("com.sun.star.comp.framework.PathSettings"); + XPropertySet pthSettings = (XPropertySet) AnyConverter.toObject( + new Type(XPropertySet.class), settings); + return (String) pthSettings.getPropertyValue(setting); + } catch (com.sun.star.uno.Exception ex) { + throw new RuntimeException(ex); + } + } + + /** + * This method returns the temp directory of the user. + * Since Java 1.4 it is not possible to read environment variables. To workaround + * this, the Java parameter -D could be used. + */ + public static String getUsersTempDir() { + String tempDir = System.getProperty("my.temp"); + if (tempDir == null) { + tempDir = System.getProperty("my.tmp"); + if (tempDir == null) { + tempDir = System.getProperty("java.io.tmpdir"); + } + } + // remove ending file separator + if (tempDir.endsWith(System.getProperty("file.separator"))) { + tempDir = tempDir.substring(0, tempDir.length() - 1); + } + + return tempDir; + } + + /** + * + * This method gets the temp dir of the connected office + * + */ + public static String getOfficeTemp(XMultiServiceFactory msf) { + String url = getOfficeUserPath(msf) + "/test-temp/"; + try { + new File(new URI(url)).mkdir(); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + return url; + } + + /** + * Gets StarOffice temp directory without 'file:///' prefix. + * For example is useful for Registry URL specifying. + * @msf Office factory for accessing its settings. + * @return SOffice temporary directory in form for example + * 'd:/Office60/user/temp/'. + */ + public static String getOfficeTempDir(XMultiServiceFactory msf) { + + String dir = getOfficeTemp(msf); + + int idx = dir.indexOf("file:///"); + + if (idx < 0) { + return dir; + } + + dir = dir.substring("file:///".length()); + + idx = dir.indexOf(':'); + + // is the last character a '/' or a '\'? + boolean lastCharSet = dir.endsWith("/") || dir.endsWith("\\"); + + if (idx < 0) { // linux or solaris + dir = "/" + dir; + dir += lastCharSet ? "" : "/"; + } else { // windows + dir += lastCharSet ? "" : "\\"; + } + + return dir; + } + + /** + * Gets StarOffice temp directory without 'file:///' prefix. + * and System dependent file separator + */ + public static String getOfficeTempDirSys(XMultiServiceFactory msf) { + + String dir = getOfficeTemp(msf); + String sysDir = ""; + + int idx = dir.indexOf("file://"); + + // remove leading 'file://' + if (idx < 0) { + sysDir = dir; + } else { + sysDir = dir.substring("file://".length()); + } + + // append '/' if not there (e.g. linux) + if (sysDir.charAt(sysDir.length() - 1) != '/') { + sysDir += "/"; + } + + // remove leading '/' and replace others with '\' on windows machines + if (sysDir.indexOf(':') != -1) { + sysDir = sysDir.substring(1); + sysDir = sysDir.replace('/', '\\'); + } + return sysDir; + } + + /** + * converts a fileURL to a system URL + * @param fileURL a file URL + * @return a system URL + */ + public static String getSystemURL(String fileURL) { + String sysDir = ""; + + int idx = fileURL.indexOf("file://"); + + // remove leading 'file://' + if (idx < 0) { + sysDir = fileURL; + } else { + sysDir = fileURL.substring("file://".length()); + } + + // remove leading '/' and replace others with '\' on windows machines + if (sysDir.indexOf(':') != -1) { + sysDir = sysDir.substring(1); + sysDir = sysDir.replace('/', '\\'); + } + return sysDir; + } + + /** + * This method check via Office the existence of the given file URL + * @param msf the multiservice factory + * @param fileURL the file which existence should be checked + * @return true if the file exists, else false + */ + public static boolean fileExists(XMultiServiceFactory msf, String fileURL) throws com.sun.star.uno.Exception { + Object fileacc = msf.createInstance("com.sun.star.comp.ucb.SimpleFileAccess"); + XSimpleFileAccess simpleAccess = UnoRuntime.queryInterface(XSimpleFileAccess.class, + fileacc); + return simpleAccess.exists(fileURL); + } + + /** + * This method deletes via office the given file URL. It checks the existence + * of <CODE>fileURL</CODE>. If exists it will be deleted. + * @param xMsf the multiservice factory + * @param fileURL the file to delete + * @return true if the file could be deleted or the file does not exist + */ + public static boolean deleteFile(XMultiServiceFactory xMsf, String fileURL) { + boolean delete = true; + try { + + Object fileacc = xMsf.createInstance("com.sun.star.comp.ucb.SimpleFileAccess"); + XSimpleFileAccess simpleAccess = UnoRuntime.queryInterface(XSimpleFileAccess.class, + fileacc); + if (simpleAccess.exists(fileURL)) { + simpleAccess.kill(fileURL); + } + + } catch (Exception e) { + System.out.println("Couldn't delete file '" + fileURL + "'"); + e.printStackTrace(); + delete = false; + } + return delete; + } + + /** + * This method copies via office a given file to a new one + * @param xMsf the multi service factory + * @param source the source file + * @param destination the destination file + * @return true at success + */ + public static boolean copyFile(XMultiServiceFactory xMsf, String source, String destination) { + boolean res = false; + try { + Object fileacc = xMsf.createInstance("com.sun.star.comp.ucb.SimpleFileAccess"); + XSimpleFileAccess simpleAccess = UnoRuntime.queryInterface(XSimpleFileAccess.class, + fileacc); + if (!simpleAccess.exists(destination)) { + simpleAccess.copy(source, destination); + } + + res = true; + } catch (Exception e) { + System.out.println("Couldn't copy file '" + source + "' -> '" + destination + "'"); + e.printStackTrace(); + res = false; + } + return res; + } + + private static void overwriteFile_impl( + XMultiServiceFactory xMsf, String oldF, String newF) + throws InteractiveAugmentedIOException + { + try { + Object fileacc = xMsf.createInstance("com.sun.star.comp.ucb.SimpleFileAccess"); + + XSimpleFileAccess simpleAccess = UnoRuntime.queryInterface(XSimpleFileAccess.class, + fileacc); + if (simpleAccess.exists(newF)) { + simpleAccess.kill(newF); + } + simpleAccess.copy(oldF, newF); + } catch (InteractiveAugmentedIOException e) { + throw e; + } catch (com.sun.star.uno.Exception ex) { + throw new RuntimeException("Could not copy " + oldF + " to " + newF, ex); + } + } + + /** + * Copies file to a new location using OpenOffice.org features. If the target + * file already exists, the file is deleted. + * + * @returns <code>true</code> if the file was successfully copied, + * <code>false</code> if some errors occurred (e.g. file is locked, used + * by another process). + */ + public static boolean tryOverwriteFile( + XMultiServiceFactory xMsf, String oldF, String newF) + { + try { + overwriteFile_impl(xMsf, oldF, newF); + } catch (InteractiveAugmentedIOException e) { + return false; + } + return true; + } + + + + public static boolean hasPropertyByName(XPropertySet props, String aName) { + Property[] list = props.getPropertySetInfo().getProperties(); + boolean res = false; + for (int i = 0; i < list.length; i++) { + String the_name = list[i].Name; + if (aName.equals(the_name)) { + res = true; + } + } + return res; + } + + /** + * + * This method returns the implementation name of a given object + * + */ + public static String getImplName(Object aObject) { + XServiceInfo xSI = UnoRuntime.queryInterface(XServiceInfo.class, aObject); + return xSI == null ? "Unknown, does not implement XServiceInfo" : xSI.getImplementationName(); + } + + /** + * + * This method checks if an Object is void + * + */ + public static boolean isVoid(Object aObject) { + if (aObject instanceof com.sun.star.uno.Any) { + com.sun.star.uno.Any oAny = (com.sun.star.uno.Any) aObject; + return oAny.getType().getTypeName().equals("void"); + } else { + return false; + } + + } + + /** + * Scan localhost for the next free port-number from a starting port + * on. If the starting port is smaller than 1024, port number starts with + * 10000 as default, because numbers < 1024 are never free on unix machines. + * @param startPort The port where scanning starts. + * @return The next free port. + */ + public static int getNextFreePort(int startPort) { + if (startPort < 1024) { + startPort = 10000; + } + for (int port = startPort; port < 65536; port++) { + System.out.println("Scan port " + port); + try { + // first trying to establish a server-socket on localhost + // fails if there is already a server running + ServerSocket sSock = new ServerSocket(port); + sSock.close(); + } catch (IOException e) { + System.out.println(" -> server: occupied port " + port); + continue; + } + try { + Socket sock = new Socket("localhost", port); + System.out.println(" -> socket: occupied port: " + port); + try { + sock.close(); + } catch (IOException ex) { + // ignore close exception + } + } catch (IOException e) { + System.out.println(" -> free port"); + return port; + } + } + return 65535; + } + + public static URL parseURL(XMultiServiceFactory xMSF, String url) { + URL[] rUrl = new URL[1]; + rUrl[0] = new URL(); + rUrl[0].Complete = url; + + XURLTransformer xTrans = null; + try { + Object inst = xMSF.createInstance("com.sun.star.util.URLTransformer"); + xTrans = UnoRuntime.queryInterface(XURLTransformer.class, inst); + } catch (com.sun.star.uno.Exception e) { + } + + if (xTrans != null) + xTrans.parseStrict(rUrl); + + return rUrl[0]; + } + + public static String getOfficeURL(XMultiServiceFactory msf) throws com.sun.star.uno.Exception { + Object settings = msf.createInstance("com.sun.star.util.PathSettings"); + XPropertySet settingProps = UnoRuntime.queryInterface(XPropertySet.class, settings); + String path = (String) settingProps.getPropertyValue("Module"); + return path; + } + + + + /** + * Get an array of all property names from the property set. With the include + * and exclude parameters the properties can be filtered. <br> + * Set excludePropertyAttribute = 0 and includePropertyAttribute = 0 + * to include all and exclude none. + * @param props The instance of XPropertySet + * @param includePropertyAttribute Properties without these attributes are filtered and will not be returned. + * @param excludePropertyAttribute Properties with these attributes are filtered and will not be returned. + * @param array of string names of properties that will be skipped + * @return A String array with all property names. + * @see com.sun.star.beans.XPropertySet + * @see com.sun.star.beans.Property + * @see com.sun.star.beans.PropertyAttribute + */ + public static String[] getFilteredPropertyNames(XPropertySet props, short includePropertyAttribute, + short excludePropertyAttribute, String[] skipList) { + Property[] the_props = props.getPropertySetInfo().getProperties(); + ArrayList<String> l = new ArrayList<String>(); + for (int i = 0; i < the_props.length; i++) { + if (Arrays.asList(skipList).contains(the_props[i].Name)) + continue; + boolean exclude = ((the_props[i].Attributes & excludePropertyAttribute) != 0); + boolean include = (includePropertyAttribute == 0) || + ((the_props[i].Attributes & includePropertyAttribute) != 0); + if (include && !exclude) { + l.add(the_props[i].Name); + } + } + Collections.sort(l); + String[] names = new String[l.size()]; + names = l.toArray(names); + return names; + } + + /** Causes the thread to sleep some time. + * This is the default call, which waits for 500ms. + */ + public static void shortWait() { + pause(utils.DEFAULT_SHORT_WAIT_MS); + } + + /** Causes the thread to sleep some time. + */ + public static void pause(int milliseconds) { + try { + Thread.sleep(milliseconds); + } catch (InterruptedException e) { + System.out.println("While waiting :" + e); + } + } + + public static void waitForEventIdle(XMultiServiceFactory xMSF) { + try { + XToolkitExperimental xToolkit = UnoRuntime.queryInterface( + XToolkitExperimental.class, + xMSF.createInstance("com.sun.star.awt.Toolkit")); + xToolkit.processEventsToIdle(); + } catch (com.sun.star.uno.Exception ex) { + throw new RuntimeException(ex); + } + } + + /** + * Validate the AppExecutionCommand. Returned is an error message, starting + * with "Error:", or a warning, if the command might work. + * @param appExecCommand The application execution command that is checked. + * @param os The operating system where the check runs. + * @return The error message, or OK, if no error was detected. + */ + public static String validateAppExecutionCommand(String appExecCommand, String os) { + String errorMessage = "OK"; + appExecCommand = appExecCommand.replace("\"", ""); + appExecCommand = appExecCommand.replace("'", ""); + StringTokenizer commandTokens = new StringTokenizer(appExecCommand, " \t"); + String officeExecCommand = "soffice"; + StringBuilder sb = new StringBuilder(); + // is there a 'soffice' in the command? 2do: eliminate case sensitivity on windows + int index = -1; + while (commandTokens.hasMoreTokens() && index == -1) { + sb.append(commandTokens.nextToken()).append(" "); + index = sb.indexOf(officeExecCommand); + } + if (index == -1) { + errorMessage = "Error: Your 'AppExecutionCommand' parameter does not " + + "contain '" + officeExecCommand + "'."; + } else { + String officeExecutable = sb.toString(); + // does the directory exist? + officeExecutable = officeExecutable.trim(); + String officePath = officeExecutable.substring(0, index); + File f = new File(officePath); + if (!f.exists() || !f.isDirectory()) { + errorMessage = "Error: Your 'AppExecutionCommand' parameter does not " + + "point to a valid system directory: " + officePath; + } else { + // is it an office installation? + f = new File(officeExecutable); + // one try for windows platform can't be wrong... + if (!f.exists() || !f.isFile()) { + f = new File(officeExecutable + ".exe"); + } + if (!f.exists() || !f.isFile()) { + errorMessage = "Error: Your 'AppExecutionCommand' parameter does not " + + "point to a valid office installation."; + } else { + // do we have the accept parameter? + boolean gotNoAccept = true; + while (commandTokens.hasMoreElements()) { + String officeParam = commandTokens.nextToken(); + if (officeParam.indexOf("--accept=") != -1) { + gotNoAccept = false; + errorMessage = validateConnectString(officeParam, true); + } + } + if (gotNoAccept) { + errorMessage = "Error: Your 'AppExecutionCommand' parameter does not " + + "contain a '--accept' parameter for connecting the office."; + } + } + } + } + return errorMessage; + } + + /** + * Validate the connection string. Returned is an error message, starting + * with "Error:", or a warning, if the command might work. + * @param connectString The connection string that is checked. + * @param checkAppExecutionCommand If the AppExecutionCommand is checked, the error message is different. + * @return The error message, or OK, if no error was detected. + */ + private static String validateConnectString(String connectString, boolean checkAppExecutionCommand) { + String acceptPrefix = ""; + if (checkAppExecutionCommand) { + acceptPrefix = "--accept="; + } + + String errorMessage = "OK"; + // a warning, if an unknown connection method is used + if (connectString.indexOf("socket") != -1) { + if (connectString.indexOf(acceptPrefix + "socket,host=") == -1 || + connectString.indexOf("port=") == -1) { + if (checkAppExecutionCommand) { + errorMessage = "Error: The '--accept' parameter contains a syntax error: It should be like: '--accept=socket,host=localhost,port=8100;urp;"; + } else { + errorMessage = "Error: The 'ConnectionString' parameter contains a syntax error: It should be like: 'socket,host=localhost,port=8100'"; + } + } + } else if (connectString.indexOf("pipe") != -1) { + if (connectString.indexOf(acceptPrefix + "pipe,name=") == -1) { + if (checkAppExecutionCommand) { + errorMessage = "Error: The '--accept' parameter contains a syntax error: It should be like: '--accept=pipe,name=myuniquename;urp;'"; + } else { + errorMessage = "Error: The 'ConnectionString' parameter contains a syntax error: It should be like: 'pipe,name=myuniquename'"; + } + } + } else { + if (checkAppExecutionCommand) { + errorMessage = "Warning: The '--accept' parameter contains an unknown connection method."; + } else { + errorMessage = "Warning: The 'ConnectionString' parameter contains an unknown connection method."; + } + } + return errorMessage; + } + + /** + * expand macrofied strings like <CODE>${$ORIGIN/bootstrap.ini:UserInstallation}</CODE> or + * <CODE>$_OS</CODE> + * @param xMSF the MultiServiceFactory + * @param expand the string to expand + * @throws java.lang.Exception was thrown on any exception + * @return return the expanded string + * @see com.sun.star.util.XMacroExpander + */ + public static String expandMacro(XMultiServiceFactory xMSF, String expand) { + try { + XPropertySet xPS = UnoRuntime.queryInterface(XPropertySet.class, xMSF); + XComponentContext xContext = UnoRuntime.queryInterface(XComponentContext.class, + xPS.getPropertyValue("DefaultContext")); + XMacroExpander xME = UnoRuntime.queryInterface(XMacroExpander.class, + xContext.getValueByName("/singletons/com.sun.star.util.theMacroExpander")); + return xME.expandMacros(expand); + } catch (Exception e) { + throw new RuntimeException("could not expand macro", e); + } + + } + + + + /** + * dispatches given <CODE>URL</CODE> to the document <CODE>XComponent</CODE> + * @param xMSF the <CODE>XMultiServiceFactory</CODE> + * @param xDoc the document where to dispatch + * @param URL the <CODE>URL</CODE> to dispatch + * @throws java.lang.Exception throws <CODE>java.lang.Exception</CODE> on any error + */ + public static void dispatchURL(XMultiServiceFactory xMSF, XComponent xDoc, String URL) throws java.lang.Exception { + XModel aModel = UnoRuntime.queryInterface(XModel.class, xDoc); + + XController xCont = aModel.getCurrentController(); + + dispatchURL(xMSF, xCont, URL); + + } + + /** + * dispatches given <CODE>URL</CODE> to the <CODE>XController</CODE> + * @param xMSF the <CODE>XMultiServiceFactory</CODE> + * @param xCont the <CODE>XController</CODE> to query for a XDispatchProvider + * @param URL the <CODE>URL</CODE> to dispatch + */ + private static void dispatchURL(XMultiServiceFactory xMSF, XController xCont, String URL) { + try { + + XDispatchProvider xDispProv = UnoRuntime.queryInterface(XDispatchProvider.class, xCont); + + XURLTransformer xParser = UnoRuntime.queryInterface( + XURLTransformer.class, + xMSF.createInstance("com.sun.star.util.URLTransformer")); + + // Because it's an in/out parameter we must use an array of URL objects. + URL[] aParseURL = new URL[1]; + aParseURL[0] = new URL(); + aParseURL[0].Complete = URL; + xParser.parseStrict(aParseURL); + + URL aURL = aParseURL[0]; + + XDispatch xDispatcher = xDispProv.queryDispatch(aURL, "", 0); + xDispatcher.dispatch(aURL, null); + + waitForEventIdle(xMSF); + + } catch (Exception e) { + throw new RuntimeException("Could not dispatch URL '" + URL + "'", e); + } + } + + /** returns a String which contains the current date and time<br> + * format: [DD.MM.YYYY - HH:MM:SS::mm] + * + ** @return a String which contains the current date and time + */ + public static String getDateTime() { + + Calendar cal = new GregorianCalendar(); + DecimalFormat dfmt = new DecimalFormat("00"); + String dateTime = dfmt.format(cal.get(Calendar.DAY_OF_MONTH)) + "." + + dfmt.format(cal.get(Calendar.MONTH) + 1) + "." + + dfmt.format(cal.get(Calendar.YEAR)) + " - " + + dfmt.format(cal.get(Calendar.HOUR_OF_DAY)) + ":" + + dfmt.format(cal.get(Calendar.MINUTE)) + ":" + + dfmt.format(cal.get(Calendar.SECOND)) + "," + + dfmt.format(cal.get(Calendar.MILLISECOND)); + return "[" + dateTime + "]"; + } + + /** + * Default short wait time for the Office + */ + public static final int DEFAULT_SHORT_WAIT_MS = 500; + + /// see rtl/math.hxx + public static boolean approxEqual( double a, double b ) + { + if( a == b ) + return true; + double x = a - b; + return (x < 0.0 ? -x : x) + < ((a < 0.0 ? -a : a) * (1.0 / (16777216.0 * 16777216.0))); + } +} |