diff options
Diffstat (limited to 'qadevOOo/runner/basicrunner/BasicHandler.java')
-rw-r--r-- | qadevOOo/runner/basicrunner/BasicHandler.java | 612 |
1 files changed, 612 insertions, 0 deletions
diff --git a/qadevOOo/runner/basicrunner/BasicHandler.java b/qadevOOo/runner/basicrunner/BasicHandler.java new file mode 100644 index 000000000000..a0f5f5e405fc --- /dev/null +++ b/qadevOOo/runner/basicrunner/BasicHandler.java @@ -0,0 +1,612 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package basicrunner; + + +import com.sun.star.beans.PropertyValue; +import com.sun.star.beans.XPropertySet; +import com.sun.star.connection.ConnectionSetupException; +import com.sun.star.container.ContainerEvent; +import com.sun.star.container.XContainer; +import com.sun.star.container.XContainerListener; +import com.sun.star.container.XNameContainer; +import com.sun.star.frame.XComponentLoader; +import com.sun.star.frame.XDesktop; +import com.sun.star.lang.WrappedTargetException; +import com.sun.star.lang.XComponent; +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.uno.Type; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.util.XChangesBatch; +import java.util.Hashtable; +import lib.TestParameters; + +import share.LogWriter; + + +/** + * This class is a java-part of BASIC-java interaction "driver" + * It is used to call Star-Basic's function from java using + * basic's part of "driver" where listeners are implemented. + * The instance of the BasicHandler should be added to the MSF that will be + * used for loading BASIC's part of "driver".<br> + * After opening basic's document it creates an instance of the + * HandlerContainer using BasicHandler. HandlerContainer is a UNO + * XContainer and XNameContainer. + * Only one instance of BasicHandler can be used at the moment. + * @see com.sun.star.lang.XServiceInfo + * @see com.sun.star.lang.XSingleServiceFactory + */ +public class BasicHandler implements XServiceInfo, XSingleServiceFactory { + /** + * serviceName is the name of service that can be created in BASIC. + */ + static final String serviceName = + "com.sun.star.jsuite.basicrunner.BasicHandler"; + + /** + * <code>container</code> is a SHARED variable (between BASIC and Java). + * It is used for interacting. + */ + static private HandlerContainer container = null; + + /** + * Contains a writer to log an information about the interface testing, to + * allows for tests to access it. + */ + static private LogWriter log; + + /** + * <code>oHandlerDoc</code> is a referrence to BASIC's document. + */ + static private XComponent oHandlerDoc = null; + + /** + * <code>xMSF</code> is a MultiServiceFactory currently used by + * BasicHandler. + */ + static private XMultiServiceFactory xMSF = null; + + /** + * Interface being tested now. + */ + static private BasicIfcTest TestedInterface = null; + + /** + * Ab enhanced scheme of timeouts can be used with BASIC tests. + * A small timeout can be used zo wait for changes in the test status. + * <code>respFlag</code> is set to <code>true</code> when a BASIC test + * writes any log information. + */ + static private boolean respFlag = false; + + /** + * <code>iBasicTimeout</code> is the amount of milliseconds that + * the BasicHandler will wait for a response from tests + * (finish to execute a method or add log information) + * before it decides that SOffice is dead. + */ + static private int iBasicTimeout = 10000; + + + + /** + * Creates an instance of a HandlerContainer. This instance is used from + * BASIC. + * @param tParam The test parameters. + */ + public BasicHandler(TestParameters tParam) { + if (tParam.get("soapi.test.basic.debugFile") != null) { + iBasicTimeout = 0; // Debug mode. + } + container = new HandlerContainer(this); + } + + /** + * Set the tested interface and a log writer. + * @param ifc The test of an interface + * @param log A log writer. + */ + public void setTestedInterface(BasicIfcTest ifc, LogWriter log) { + this.log = log; + TestedInterface = ifc; + } + + /** + * Is called when BASIC signals that it has performed the test of a method. + * @param methodName The name of the method. + * @bResult The result of the test. + */ + synchronized void methodTested(String methodName, boolean bResult) { + respFlag = true; + TestedInterface.methodTested(methodName, bResult); + notify() ; + } + + /** + * Is called when BASIC sends a signal to write some log information. + * @param info The string to write. + */ + synchronized public void Log(String info) { + respFlag = true; + log.println(info); + notify() ; + } + + /** + * Is called by BasicIfcTest to find out if this BasicHandler uses the + * correct MultiServiceFactory. + * @param xMSF The MultiServiceFactory + * @see com.sun.star.lang.XMultiServiceFactory + * @return True, if xMSF is equal to the MultiServiceFactory of this class. + */ + public boolean isUptodate(XMultiServiceFactory xMSF) { + return xMSF.equals(this.xMSF); + } + + + /** + * Establishes a connection between BASIC and Java. + * If required, hte BASIC part of the "driver" is loaded. + * @param sBasicBridgeURL The URL of the basic bridge document + * (BasicBridge.sxw) + * @param tParam The test parameters. + * @param xMSF The MultiServiceFactory + * @param log The log writer. + * @see com.sun.star.lang.XMultiServiceFactory + * @throws ConnectionSetupException Exception is thrown, if no connection could be made. + */ + public synchronized void Connect(String sBasicBridgeURL, + TestParameters tParam, XMultiServiceFactory xMSF, + LogWriter log) throws ConnectionSetupException { + this.log = log; + try { + this.xMSF = xMSF; + Object oInterface = xMSF.createInstance( + "com.sun.star.frame.Desktop"); + XDesktop oDesktop = (XDesktop) UnoRuntime.queryInterface( + XDesktop.class, oInterface); + XComponentLoader oCLoader = (XComponentLoader) + UnoRuntime.queryInterface( + XComponentLoader.class, oDesktop); + + // load BasicBridge with MarcoEceutionMode = Always-no warn + //PropertyValue[] DocArgs = null; + PropertyValue[] DocArgs = new PropertyValue[1]; + PropertyValue DocArg = new PropertyValue(); + DocArg.Name = "MacroExecutionMode"; + DocArg.Value = new Short( + com.sun.star.document.MacroExecMode.ALWAYS_EXECUTE_NO_WARN); + DocArgs[0] = DocArg; + + // configure Office to allow to execute macos + PropertyValue [] ProvArgs = new PropertyValue [1]; + PropertyValue Arg = new PropertyValue(); + Arg.Name = "nodepath"; + Arg.Value = "/org.openoffice.Office.Common/Security"; + ProvArgs[0] = Arg; + + Object oProvider = xMSF.createInstance( + "com.sun.star.configuration.ConfigurationProvider"); + + XMultiServiceFactory oProviderMSF = (XMultiServiceFactory) + UnoRuntime.queryInterface( + XMultiServiceFactory.class, oProvider); + + Object oSecure = oProviderMSF.createInstanceWithArguments( + "com.sun.star.configuration.ConfigurationUpdateAccess", + ProvArgs); + + XPropertySet oSecureProps = (XPropertySet) + UnoRuntime.queryInterface(XPropertySet.class, oSecure); + + Object oScripting = oSecureProps.getPropertyValue("Scripting"); + XPropertySet oScriptingSettings = (XPropertySet) + UnoRuntime.queryInterface(XPropertySet.class, oScripting); + + oScriptingSettings.setPropertyValue("Warning", Boolean.FALSE); + oScriptingSettings.setPropertyValue("OfficeBasic", new Integer(2)); + + XChangesBatch oSecureChange = (XChangesBatch) + UnoRuntime.queryInterface(XChangesBatch.class, oSecure); + oSecureChange.commitChanges(); + + // As we want to have some information about a debugFile + // BEFORE connection is established + // we pass the information about it in frame name. + String sFrameName = (String)tParam.get( + "soapi.test.basic.debugFile"); + if (sFrameName == null) sFrameName = "BasicRunner"; + + oHandlerDoc = oCLoader.loadComponentFromURL(sBasicBridgeURL, + sFrameName, 40, DocArgs); + + do { + respFlag = false ; + wait(10000); // waiting for basic response for 10 seconds. + } while (respFlag && !container.hasByName("BASIC_Done")) ; + + if (!container.hasByName("BASIC_Done")) { + throw new ConnectionSetupException("Connection timed out."); + } + } catch (Exception e) { + System.out.println("Exception: " + e.toString()); + throw new ConnectionSetupException(); + } + + log.println("Java-BASIC connection established!"); + } + + /** + * Overloads perform(Strin fName, Object params) for convenience. + * @return A proprty value as result. + * + public synchronized PropertyValue perform(String fName) + throws BasicException { + return perform(fName, ""); + } +*/ + /** + * Perform a test of a method. + * @param fName The name of the method to test. + * @param params The test parameters. + * @return A proprty value as result of the test. + * @throws BasicException The method could not be executed. + */ + public synchronized PropertyValue perform(String fName, Object params) + throws BasicException { + try { + container.callBasicFunction(fName, params); + + do { + respFlag = false; + // waiting for basic response for iBasicTimeout milliseconds. + wait(iBasicTimeout); + } while(respFlag && !container.hasByName("BASIC_Done")); + + } catch (InterruptedException e) { + System.out.println("The operation " + fName + " was interrupted."); + } catch (com.sun.star.lang.DisposedException de) { + System.out.println("## Office is disposed"); + } + + if (!container.hasByName("BASIC_Done")) { + System.out.println("Operation timed out."); + throw new BasicException( + "Operation timed out."); + } + + Object res = container.getByName("BASIC_Done") ; + container.removeByName("BASIC_Done"); + + if (!(res instanceof PropertyValue)) { + if (res == null) { + System.out.println( + "BasicBridge returns null"); + throw new BasicException( + "BasicBridge returns null"); + } else { + System.out.println( + "BasicBridge returns wrong type: " + res.getClass()); + throw new BasicException( + "BasicBridge returns wrong type: " + res.getClass()); + } + } + + PropertyValue result = (PropertyValue) res ; + + if ((result.Value instanceof String) && (((String)result.Value)).startsWith("Exception")) { + throw new BasicException((String)result.Value); + } + + return result; + } + + /** + * Returns true, if name is a supported service of this class. + * @param name The service name. + * @return True, if the service is supported. + */ + public boolean supportsService(String name) { + return serviceName.equals(name); + } + + /** + * Return all supported service names. + * @return All supported services. + */ + public String[] getSupportedServiceNames() { + return new String[] {serviceName}; + } + + /** + * Get the implementation name. + * @return Implementation name. + */ + public String getImplementationName() { + return getClass().getName(); + } + + /** + * Create an instance of HandlerContainer. + * Arguments are not supported here, so they will be ignored. + * @param args The arguments. + * @return The instance. + */ + public Object createInstanceWithArguments(Object[] args) { + return container; + } + + /** + * Create an instance of HandlerContainer. + * @return The instance. + */ + public Object createInstance() { + return createInstanceWithArguments(null); + } + + /** + * Dispose the BASIC document. + */ + public synchronized void dispose() { + try { + if (oHandlerDoc != null) { + //oHandlerDoc.dispose(); + util.DesktopTools.closeDoc(oHandlerDoc); + wait(1000); + } + } catch (Exception e) { + System.out.println("Exception: " + e.toString()); + } + } +} + + +/** + * This class handles the communication between Java and BASIC. + * @see com.sun.star.container.XContainer + * @see com.sun.star.container.XNameContainer + * @see com.sun.star.lang.XTypeProvider + */ +class HandlerContainer implements XContainer, XNameContainer, XTypeProvider{ + + /** Container for parameters. + **/ + Hashtable container = new Hashtable(20); + /** + * An array of listeners for container events. + * @see com.sun.star.container.XContainerListener + */ + static XContainerListener[] listener = null; + + /** The BasicHandler belonging to this handler. **/ + BasicHandler parent = null; + + /** + * Constructor with the parent BasicHandler. + * @param par The BasicHandler. + */ + public HandlerContainer(BasicHandler par) { + parent = par; + } + + /** + * Call a BASIC function, meaning a test method. + * @param fName The method name. + * @param args Arguments for the method. + */ + public void callBasicFunction(String fName, Object args) { + // BASIC's listener should be called ONLY in this case. + if (container.containsKey(fName)) { + container.remove(fName); + } + container.put(fName, args); + if (listener != null) { + ContainerEvent event = new ContainerEvent(); + event.Element = fName; + for (int i=0; i<listener.length; i++){ + if (listener[i] != null) { + listener[i].elementInserted(event); + } + } + } + } + + /** + * Insert an object into the container. + * @param name The key for the object. + * @param object The object to insert. + * @throws IllegalArgumentException Throws this exception when trying to insert null. + */ + public void insertByName(String name, Object object) throws com.sun.star.lang.IllegalArgumentException, com.sun.star.container.ElementExistException, com.sun.star.lang.WrappedTargetException { + + // BASIC and Java can insert into the container. + if (container.containsKey(name)) { + container.remove(name); + } + container.put(name, object); + + PropertyValue result = null ; + + if (object instanceof PropertyValue) { + result = (PropertyValue)object; + if (name.equals("BASIC_Done")) { + synchronized (parent) { + parent.notify(); + } + } else if (name.equals("BASIC_MethodTested")) { + parent.methodTested(result.Name, + ((Boolean)result.Value).booleanValue()); + } + } else if (name.equals("BASIC_Log")) { + parent.Log(object.toString()); + } + } + + /** + * Remove the object with this name from the container. + * @param name The key. + */ + public void removeByName(String name) { + container.remove(name) ; + } + + /** + * Unsupported method. + * @param name The name of the key. + * @param value The value. + * @throws WrappedTargetException Throws this exception when called falsely. + */ + public void replaceByName(String name, Object value) + throws WrappedTargetException { + throw new WrappedTargetException("Unsupported"); + } + + /** + * Has a value for this key. + * @param name The name of a key. + * @return True, if name exists as key in the container. + */ + public boolean hasByName(String name) { + return container.containsKey(name); + } + + /** + * Get an object by its key. + * @param name The name of the key. + * @return The object of this key. + */ + public Object getByName(String name) { + return container.get(name); + } + + /** + * Get all key names. + * @return All names of keys. + */ + public String[] getElementNames() { + String[] res = new String[container.size()]; + return (String[])container.keySet().toArray(res); + } + + /** + * Is the xcontainer empty? + * @return True, if the container has elements. + */ + public boolean hasElements() { + return !container.isEmpty(); + } + + /** + * Get the type of this class. + * @return The type of this class. + */ + public Type getElementType() { + try { + return new Type(String.class); + } catch (Exception e) { + return null; + } + } + + /** + * Get the implementation id of this class. + * @return A unique id for this class + * @see com.sun.star.lang.XTypeProvider + */ + public byte[] getImplementationId() { + return toString().getBytes(); + } + + /** + * Get all types of this class. + * @return All implemented UNO types. + */ + public Type[] getTypes() { + Class interfaces[] = getClass().getInterfaces(); + Type types[] = new Type[interfaces.length]; + for(int i = 0; i < interfaces.length; ++ i) { + types[i] = new Type(interfaces[i]); + } + return types; + } + + /** + * Add a listener + * @param xListener The listener. + */ + public void addContainerListener(XContainerListener xListener){ + int length = 0; + if (listener != null) + length = listener.length; + + XContainerListener[] mListener = + new XContainerListener[length+1]; + for (int i=0; i<length-1; i++) { + mListener[i] = listener[i]; + // listener already added + if (((Object)xListener).equals(listener[i])) + return; + } + mListener[length] = xListener; + listener = mListener; + } + + /** + * Remove a listener + * @param xListener The listener. + */ + public void removeContainerListener(XContainerListener xListener){ + if (listener != null && listener.length != 0) { + int length = listener.length; + XContainerListener[] mListener = + new XContainerListener[length-1]; + boolean found = false; + int j=0; + for (int i=0; i<length-1; i++) { + if (!((Object)xListener).equals(listener[j])) { + mListener[i] = listener[j]; + } + else { + j++; + found = true; + } + j++; + } + if (!found) { + if (((Object)xListener).equals(listener[length-1])) + listener = mListener; + } + else + listener = mListener; + + } + } +} |