merge the formfield patch from ooo-build
[ooovba.git] / qadevOOo / runner / basicrunner / BasicHandler.java
bloba153f3c69717ff9cd690f62758b5aae15a49888d
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: BasicHandler.java,v $
10 * $Revision: 1.5 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
30 package basicrunner;
33 import com.sun.star.beans.PropertyValue;
34 import com.sun.star.beans.XPropertySet;
35 import com.sun.star.connection.ConnectionSetupException;
36 import com.sun.star.container.ContainerEvent;
37 import com.sun.star.container.XContainer;
38 import com.sun.star.container.XContainerListener;
39 import com.sun.star.container.XNameContainer;
40 import com.sun.star.frame.XComponentLoader;
41 import com.sun.star.frame.XDesktop;
42 import com.sun.star.lang.WrappedTargetException;
43 import com.sun.star.lang.XComponent;
44 import com.sun.star.lang.XMultiServiceFactory;
45 import com.sun.star.lang.XServiceInfo;
46 import com.sun.star.lang.XSingleServiceFactory;
47 import com.sun.star.lang.XTypeProvider;
48 import com.sun.star.uno.Type;
49 import com.sun.star.uno.UnoRuntime;
50 import com.sun.star.util.XChangesBatch;
51 import java.util.Hashtable;
52 import lib.TestParameters;
54 import share.LogWriter;
57 /**
58 * This class is a java-part of BASIC-java interaction "driver"
59 * It is used to call Star-Basic's function from java using
60 * basic's part of "driver" where listeners are implemented.
61 * The instance of the BasicHandler should be added to the MSF that will be
62 * used for loading BASIC's part of "driver".<br>
63 * After opening basic's document it creates an instance of the
64 * HandlerContainer using BasicHandler. HandlerContainer is a UNO
65 * XContainer and XNameContainer.
66 * Only one instance of BasicHandler can be used at the moment.
67 * @see com.sun.star.lang.XServiceInfo
68 * @see com.sun.star.lang.XSingleServiceFactory
70 public class BasicHandler implements XServiceInfo, XSingleServiceFactory {
71 /**
72 * serviceName is the name of service that can be created in BASIC.
74 static final String serviceName =
75 "com.sun.star.jsuite.basicrunner.BasicHandler";
77 /**
78 * <code>container</code> is a SHARED variable (between BASIC and Java).
79 * It is used for interacting.
81 static private HandlerContainer container = null;
83 /**
84 * Contains a writer to log an information about the interface testing, to
85 * allows for tests to access it.
87 static private LogWriter log;
89 /**
90 * <code>oHandlerDoc</code> is a referrence to BASIC's document.
92 static private XComponent oHandlerDoc = null;
94 /**
95 * <code>xMSF</code> is a MultiServiceFactory currently used by
96 * BasicHandler.
98 static private XMultiServiceFactory xMSF = null;
101 * Interface being tested now.
103 static private BasicIfcTest TestedInterface = null;
106 * Ab enhanced scheme of timeouts can be used with BASIC tests.
107 * A small timeout can be used zo wait for changes in the test status.
108 * <code>respFlag</code> is set to <code>true</code> when a BASIC test
109 * writes any log information.
111 static private boolean respFlag = false;
114 * <code>iBasicTimeout</code> is the amount of milliseconds that
115 * the BasicHandler will wait for a response from tests
116 * (finish to execute a method or add log information)
117 * before it decides that SOffice is dead.
119 static private int iBasicTimeout = 10000;
124 * Creates an instance of a HandlerContainer. This instance is used from
125 * BASIC.
126 * @param tParam The test parameters.
128 public BasicHandler(TestParameters tParam) {
129 if (tParam.get("soapi.test.basic.debugFile") != null) {
130 iBasicTimeout = 0; // Debug mode.
132 container = new HandlerContainer(this);
136 * Set the tested interface and a log writer.
137 * @param ifc The test of an interface
138 * @param log A log writer.
140 public void setTestedInterface(BasicIfcTest ifc, LogWriter log) {
141 this.log = log;
142 TestedInterface = ifc;
146 * Is called when BASIC signals that it has performed the test of a method.
147 * @param methodName The name of the method.
148 * @bResult The result of the test.
150 synchronized void methodTested(String methodName, boolean bResult) {
151 respFlag = true;
152 TestedInterface.methodTested(methodName, bResult);
153 notify() ;
157 * Is called when BASIC sends a signal to write some log information.
158 * @param info The string to write.
160 synchronized public void Log(String info) {
161 respFlag = true;
162 log.println(info);
163 notify() ;
167 * Is called by BasicIfcTest to find out if this BasicHandler uses the
168 * correct MultiServiceFactory.
169 * @param xMSF The MultiServiceFactory
170 * @see com.sun.star.lang.XMultiServiceFactory
171 * @return True, if xMSF is equal to the MultiServiceFactory of this class.
173 public boolean isUptodate(XMultiServiceFactory xMSF) {
174 return xMSF.equals(this.xMSF);
179 * Establishes a connection between BASIC and Java.
180 * If required, hte BASIC part of the "driver" is loaded.
181 * @param sBasicBridgeURL The URL of the basic bridge document
182 * (BasicBridge.sxw)
183 * @param tParam The test parameters.
184 * @param xMSF The MultiServiceFactory
185 * @param log The log writer.
186 * @see com.sun.star.lang.XMultiServiceFactory
187 * @throws ConnectionSetupException Exception is thrown, if no connection could be made.
189 public synchronized void Connect(String sBasicBridgeURL,
190 TestParameters tParam, XMultiServiceFactory xMSF,
191 LogWriter log) throws ConnectionSetupException {
192 this.log = log;
193 try {
194 this.xMSF = xMSF;
195 Object oInterface = xMSF.createInstance(
196 "com.sun.star.frame.Desktop");
197 XDesktop oDesktop = (XDesktop) UnoRuntime.queryInterface(
198 XDesktop.class, oInterface);
199 XComponentLoader oCLoader = (XComponentLoader)
200 UnoRuntime.queryInterface(
201 XComponentLoader.class, oDesktop);
203 // load BasicBridge with MarcoEceutionMode = Always-no warn
204 //PropertyValue[] DocArgs = null;
205 PropertyValue[] DocArgs = new PropertyValue[1];
206 PropertyValue DocArg = new PropertyValue();
207 DocArg.Name = "MacroExecutionMode";
208 DocArg.Value = new Short(
209 com.sun.star.document.MacroExecMode.ALWAYS_EXECUTE_NO_WARN);
210 DocArgs[0] = DocArg;
212 // configure Office to allow to execute macos
213 PropertyValue [] ProvArgs = new PropertyValue [1];
214 PropertyValue Arg = new PropertyValue();
215 Arg.Name = "nodepath";
216 Arg.Value = "/org.openoffice.Office.Common/Security";
217 ProvArgs[0] = Arg;
219 Object oProvider = xMSF.createInstance(
220 "com.sun.star.configuration.ConfigurationProvider");
222 XMultiServiceFactory oProviderMSF = (XMultiServiceFactory)
223 UnoRuntime.queryInterface(
224 XMultiServiceFactory.class, oProvider);
226 Object oSecure = oProviderMSF.createInstanceWithArguments(
227 "com.sun.star.configuration.ConfigurationUpdateAccess",
228 ProvArgs);
230 XPropertySet oSecureProps = (XPropertySet)
231 UnoRuntime.queryInterface(XPropertySet.class, oSecure);
233 Object oScripting = oSecureProps.getPropertyValue("Scripting");
234 XPropertySet oScriptingSettings = (XPropertySet)
235 UnoRuntime.queryInterface(XPropertySet.class, oScripting);
237 oScriptingSettings.setPropertyValue("Warning", Boolean.FALSE);
238 oScriptingSettings.setPropertyValue("OfficeBasic", new Integer(2));
240 XChangesBatch oSecureChange = (XChangesBatch)
241 UnoRuntime.queryInterface(XChangesBatch.class, oSecure);
242 oSecureChange.commitChanges();
244 // As we want to have some information about a debugFile
245 // BEFORE connection is established
246 // we pass the information about it in frame name.
247 String sFrameName = (String)tParam.get(
248 "soapi.test.basic.debugFile");
249 if (sFrameName == null) sFrameName = "BasicRunner";
251 oHandlerDoc = oCLoader.loadComponentFromURL(sBasicBridgeURL,
252 sFrameName, 40, DocArgs);
254 do {
255 respFlag = false ;
256 wait(10000); // waiting for basic response for 10 seconds.
257 } while (respFlag && !container.hasByName("BASIC_Done")) ;
259 if (!container.hasByName("BASIC_Done")) {
260 throw new ConnectionSetupException("Connection timed out.");
262 } catch (Exception e) {
263 System.out.println("Exception: " + e.toString());
264 throw new ConnectionSetupException();
267 log.println("Java-BASIC connection established!");
271 * Overloads perform(Strin fName, Object params) for convenience.
272 * @return A proprty value as result.
274 public synchronized PropertyValue perform(String fName)
275 throws BasicException {
276 return perform(fName, "");
280 * Perform a test of a method.
281 * @param fName The name of the method to test.
282 * @param params The test parameters.
283 * @return A proprty value as result of the test.
284 * @throws BasicException The method could not be executed.
286 public synchronized PropertyValue perform(String fName, Object params)
287 throws BasicException {
288 try {
289 container.callBasicFunction(fName, params);
291 do {
292 respFlag = false;
293 // waiting for basic response for iBasicTimeout milliseconds.
294 wait(iBasicTimeout);
295 } while(respFlag && !container.hasByName("BASIC_Done"));
297 } catch (InterruptedException e) {
298 System.out.println("The operation " + fName + " was interrupted.");
299 } catch (com.sun.star.lang.DisposedException de) {
300 System.out.println("## Office is disposed");
303 if (!container.hasByName("BASIC_Done")) {
304 System.out.println("Operation timed out.");
305 throw new BasicException(
306 "Operation timed out.");
309 Object res = container.getByName("BASIC_Done") ;
310 container.removeByName("BASIC_Done");
312 if (!(res instanceof PropertyValue)) {
313 if (res == null) {
314 System.out.println(
315 "BasicBridge returns null");
316 throw new BasicException(
317 "BasicBridge returns null");
318 } else {
319 System.out.println(
320 "BasicBridge returns wrong type: " + res.getClass());
321 throw new BasicException(
322 "BasicBridge returns wrong type: " + res.getClass());
326 PropertyValue result = (PropertyValue) res ;
328 if ((result.Value instanceof String) && (((String)result.Value)).startsWith("Exception")) {
329 throw new BasicException((String)result.Value);
332 return result;
336 * Returns true, if name is a supported service of this class.
337 * @param name The service name.
338 * @return True, if the service is supported.
340 public boolean supportsService(String name) {
341 return serviceName.equals(name);
345 * Return all supported service names.
346 * @return All supported services.
348 public String[] getSupportedServiceNames() {
349 return new String[] {serviceName};
353 * Get the implementation name.
354 * @return Implementation name.
356 public String getImplementationName() {
357 return getClass().getName();
360 /**
361 * Create an instance of HandlerContainer.
362 * Arguments are not supported here, so they will be ignored.
363 * @param args The arguments.
364 * @return The instance.
366 public Object createInstanceWithArguments(Object[] args) {
367 return container;
370 /**
371 * Create an instance of HandlerContainer.
372 * @return The instance.
374 public Object createInstance() {
375 return createInstanceWithArguments(null);
379 * Dispose the BASIC document.
381 public synchronized void dispose() {
382 try {
383 if (oHandlerDoc != null) {
384 //oHandlerDoc.dispose();
385 util.DesktopTools.closeDoc(oHandlerDoc);
386 wait(1000);
388 } catch (Exception e) {
389 System.out.println("Exception: " + e.toString());
396 * This class handles the communication between Java and BASIC.
397 * @see com.sun.star.container.XContainer
398 * @see com.sun.star.container.XNameContainer
399 * @see com.sun.star.lang.XTypeProvider
401 class HandlerContainer implements XContainer, XNameContainer, XTypeProvider{
403 /** Container for parameters.
405 Hashtable container = new Hashtable(20);
407 * An array of listeners for container events.
408 * @see com.sun.star.container.XContainerListener
410 static XContainerListener[] listener = null;
412 /** The BasicHandler belonging to this handler. **/
413 BasicHandler parent = null;
416 * Constructor with the parent BasicHandler.
417 * @param par The BasicHandler.
419 public HandlerContainer(BasicHandler par) {
420 parent = par;
424 * Call a BASIC function, meaning a test method.
425 * @param fName The method name.
426 * @param args Arguments for the method.
428 public void callBasicFunction(String fName, Object args) {
429 // BASIC's listener should be called ONLY in this case.
430 if (container.containsKey(fName)) {
431 container.remove(fName);
433 container.put(fName, args);
434 if (listener != null) {
435 ContainerEvent event = new ContainerEvent();
436 event.Element = fName;
437 for (int i=0; i<listener.length; i++){
438 if (listener[i] != null) {
439 listener[i].elementInserted(event);
446 * Insert an object into the container.
447 * @param name The key for the object.
448 * @param object The object to insert.
449 * @throws IllegalArgumentException Throws this exception when trying to insert null.
451 public void insertByName(String name, Object object) throws com.sun.star.lang.IllegalArgumentException, com.sun.star.container.ElementExistException, com.sun.star.lang.WrappedTargetException {
453 // BASIC and Java can insert into the container.
454 if (container.containsKey(name)) {
455 container.remove(name);
457 container.put(name, object);
459 PropertyValue result = null ;
461 if (object instanceof PropertyValue) {
462 result = (PropertyValue)object;
463 if (name.equals("BASIC_Done")) {
464 synchronized (parent) {
465 parent.notify();
467 } else if (name.equals("BASIC_MethodTested")) {
468 parent.methodTested(result.Name,
469 ((Boolean)result.Value).booleanValue());
471 } else if (name.equals("BASIC_Log")) {
472 parent.Log(object.toString());
477 * Remove the object with this name from the container.
478 * @param name The key.
480 public void removeByName(String name) {
481 container.remove(name) ;
485 * Unsupported method.
486 * @param name The name of the key.
487 * @param value The value.
488 * @throws WrappedTargetException Throws this exception when called falsely.
490 public void replaceByName(String name, Object value)
491 throws WrappedTargetException {
492 throw new WrappedTargetException("Unsupported");
496 * Has a value for this key.
497 * @param name The name of a key.
498 * @return True, if name exists as key in the container.
500 public boolean hasByName(String name) {
501 return container.containsKey(name);
505 * Get an object by its key.
506 * @param name The name of the key.
507 * @return The object of this key.
509 public Object getByName(String name) {
510 return container.get(name);
514 * Get all key names.
515 * @return All names of keys.
517 public String[] getElementNames() {
518 String[] res = new String[container.size()];
519 return (String[])container.keySet().toArray(res);
523 * Is the xcontainer empty?
524 * @return True, if the container has elements.
526 public boolean hasElements() {
527 return !container.isEmpty();
531 * Get the type of this class.
532 * @return The type of this class.
534 public Type getElementType() {
535 try {
536 return new Type(String.class);
537 } catch (Exception e) {
538 return null;
543 * Get the implementation id of this class.
544 * @return A unique id for this class
545 * @see com.sun.star.lang.XTypeProvider
547 public byte[] getImplementationId() {
548 return toString().getBytes();
552 * Get all types of this class.
553 * @return All implemented UNO types.
555 public Type[] getTypes() {
556 Class interfaces[] = getClass().getInterfaces();
557 Type types[] = new Type[interfaces.length];
558 for(int i = 0; i < interfaces.length; ++ i) {
559 types[i] = new Type(interfaces[i]);
561 return types;
565 * Add a listener
566 * @param xListener The listener.
568 public void addContainerListener(XContainerListener xListener){
569 int length = 0;
570 if (listener != null)
571 length = listener.length;
573 XContainerListener[] mListener =
574 new XContainerListener[length+1];
575 for (int i=0; i<length-1; i++) {
576 mListener[i] = listener[i];
577 // listener already added
578 if (((Object)xListener).equals(listener[i]))
579 return;
581 mListener[length] = xListener;
582 listener = mListener;
586 * Remove a listener
587 * @param xListener The listener.
589 public void removeContainerListener(XContainerListener xListener){
590 if (listener != null && listener.length != 0) {
591 int length = listener.length;
592 XContainerListener[] mListener =
593 new XContainerListener[length-1];
594 boolean found = false;
595 int j=0;
596 for (int i=0; i<length-1; i++) {
597 if (!((Object)xListener).equals(listener[j])) {
598 mListener[i] = listener[j];
600 else {
601 j++;
602 found = true;
604 j++;
606 if (!found) {
607 if (((Object)xListener).equals(listener[length-1]))
608 listener = mListener;
610 else
611 listener = mListener;