1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski package basicrunner;
24*b1cdbd2cSJim Jagielski 
25*b1cdbd2cSJim Jagielski 
26*b1cdbd2cSJim Jagielski import com.sun.star.beans.PropertyValue;
27*b1cdbd2cSJim Jagielski import com.sun.star.beans.XPropertySet;
28*b1cdbd2cSJim Jagielski import com.sun.star.connection.ConnectionSetupException;
29*b1cdbd2cSJim Jagielski import com.sun.star.container.ContainerEvent;
30*b1cdbd2cSJim Jagielski import com.sun.star.container.XContainer;
31*b1cdbd2cSJim Jagielski import com.sun.star.container.XContainerListener;
32*b1cdbd2cSJim Jagielski import com.sun.star.container.XNameContainer;
33*b1cdbd2cSJim Jagielski import com.sun.star.frame.XComponentLoader;
34*b1cdbd2cSJim Jagielski import com.sun.star.frame.XDesktop;
35*b1cdbd2cSJim Jagielski import com.sun.star.lang.WrappedTargetException;
36*b1cdbd2cSJim Jagielski import com.sun.star.lang.XComponent;
37*b1cdbd2cSJim Jagielski import com.sun.star.lang.XMultiServiceFactory;
38*b1cdbd2cSJim Jagielski import com.sun.star.lang.XServiceInfo;
39*b1cdbd2cSJim Jagielski import com.sun.star.lang.XSingleServiceFactory;
40*b1cdbd2cSJim Jagielski import com.sun.star.lang.XTypeProvider;
41*b1cdbd2cSJim Jagielski import com.sun.star.uno.Type;
42*b1cdbd2cSJim Jagielski import com.sun.star.uno.UnoRuntime;
43*b1cdbd2cSJim Jagielski import com.sun.star.util.XChangesBatch;
44*b1cdbd2cSJim Jagielski import java.util.Hashtable;
45*b1cdbd2cSJim Jagielski import lib.TestParameters;
46*b1cdbd2cSJim Jagielski 
47*b1cdbd2cSJim Jagielski import share.LogWriter;
48*b1cdbd2cSJim Jagielski 
49*b1cdbd2cSJim Jagielski 
50*b1cdbd2cSJim Jagielski /**
51*b1cdbd2cSJim Jagielski  * This class is a java-part of BASIC-java interaction "driver"
52*b1cdbd2cSJim Jagielski  * It is used to call Star-Basic's function from java using
53*b1cdbd2cSJim Jagielski  * basic's part of "driver" where listeners are implemented.
54*b1cdbd2cSJim Jagielski  * The instance of the BasicHandler should be added to the MSF that will be
55*b1cdbd2cSJim Jagielski  * used for loading BASIC's part of "driver".<br>
56*b1cdbd2cSJim Jagielski  * After opening basic's document it creates an instance of the
57*b1cdbd2cSJim Jagielski  * HandlerContainer using BasicHandler. HandlerContainer is a UNO
58*b1cdbd2cSJim Jagielski  * XContainer and XNameContainer.
59*b1cdbd2cSJim Jagielski  * Only one instance of BasicHandler can be used at the moment.
60*b1cdbd2cSJim Jagielski  * @see com.sun.star.lang.XServiceInfo
61*b1cdbd2cSJim Jagielski  * @see com.sun.star.lang.XSingleServiceFactory
62*b1cdbd2cSJim Jagielski  */
63*b1cdbd2cSJim Jagielski public class BasicHandler implements XServiceInfo, XSingleServiceFactory {
64*b1cdbd2cSJim Jagielski     /**
65*b1cdbd2cSJim Jagielski      * serviceName is the name of service that can be created in BASIC.
66*b1cdbd2cSJim Jagielski      */
67*b1cdbd2cSJim Jagielski     static final String serviceName =
68*b1cdbd2cSJim Jagielski                             "com.sun.star.jsuite.basicrunner.BasicHandler";
69*b1cdbd2cSJim Jagielski 
70*b1cdbd2cSJim Jagielski     /**
71*b1cdbd2cSJim Jagielski      * <code>container</code> is a SHARED variable (between BASIC and Java).
72*b1cdbd2cSJim Jagielski      * It is used for interacting.
73*b1cdbd2cSJim Jagielski      */
74*b1cdbd2cSJim Jagielski     static private HandlerContainer container = null;
75*b1cdbd2cSJim Jagielski 
76*b1cdbd2cSJim Jagielski     /**
77*b1cdbd2cSJim Jagielski      * Contains a writer to log an information about the interface testing, to
78*b1cdbd2cSJim Jagielski      * allows for tests to access it.
79*b1cdbd2cSJim Jagielski      */
80*b1cdbd2cSJim Jagielski     static private LogWriter log;
81*b1cdbd2cSJim Jagielski 
82*b1cdbd2cSJim Jagielski     /**
83*b1cdbd2cSJim Jagielski      * <code>oHandlerDoc</code> is a referrence to BASIC's document.
84*b1cdbd2cSJim Jagielski      */
85*b1cdbd2cSJim Jagielski     static private XComponent oHandlerDoc = null;
86*b1cdbd2cSJim Jagielski 
87*b1cdbd2cSJim Jagielski     /**
88*b1cdbd2cSJim Jagielski      * <code>xMSF</code> is a MultiServiceFactory currently used by
89*b1cdbd2cSJim Jagielski      * BasicHandler.
90*b1cdbd2cSJim Jagielski      */
91*b1cdbd2cSJim Jagielski     static private XMultiServiceFactory xMSF = null;
92*b1cdbd2cSJim Jagielski 
93*b1cdbd2cSJim Jagielski     /**
94*b1cdbd2cSJim Jagielski      * Interface being tested now.
95*b1cdbd2cSJim Jagielski      */
96*b1cdbd2cSJim Jagielski     static private BasicIfcTest TestedInterface = null;
97*b1cdbd2cSJim Jagielski 
98*b1cdbd2cSJim Jagielski     /**
99*b1cdbd2cSJim Jagielski      * Ab enhanced scheme of timeouts can be used with BASIC tests.
100*b1cdbd2cSJim Jagielski      * A small timeout can be used zo wait for changes in the test status.
101*b1cdbd2cSJim Jagielski      * <code>respFlag</code> is set to <code>true</code> when a BASIC test
102*b1cdbd2cSJim Jagielski      * writes any log information.
103*b1cdbd2cSJim Jagielski      */
104*b1cdbd2cSJim Jagielski     static private boolean respFlag = false;
105*b1cdbd2cSJim Jagielski 
106*b1cdbd2cSJim Jagielski     /**
107*b1cdbd2cSJim Jagielski      * <code>iBasicTimeout</code> is the amount of milliseconds that
108*b1cdbd2cSJim Jagielski      * the BasicHandler will wait for a response from tests
109*b1cdbd2cSJim Jagielski      * (finish to execute a method or add log information)
110*b1cdbd2cSJim Jagielski      * before it decides that SOffice is dead.
111*b1cdbd2cSJim Jagielski      */
112*b1cdbd2cSJim Jagielski     static private int iBasicTimeout = 10000;
113*b1cdbd2cSJim Jagielski 
114*b1cdbd2cSJim Jagielski 
115*b1cdbd2cSJim Jagielski 
116*b1cdbd2cSJim Jagielski     /**
117*b1cdbd2cSJim Jagielski      * Creates an instance of a HandlerContainer. This instance is used from
118*b1cdbd2cSJim Jagielski      * BASIC.
119*b1cdbd2cSJim Jagielski      * @param tParam The test parameters.
120*b1cdbd2cSJim Jagielski      */
BasicHandler(TestParameters tParam)121*b1cdbd2cSJim Jagielski     public BasicHandler(TestParameters tParam) {
122*b1cdbd2cSJim Jagielski         if (tParam.get("soapi.test.basic.debugFile") != null) {
123*b1cdbd2cSJim Jagielski             iBasicTimeout = 0; // Debug mode.
124*b1cdbd2cSJim Jagielski         }
125*b1cdbd2cSJim Jagielski         container = new HandlerContainer(this);
126*b1cdbd2cSJim Jagielski     }
127*b1cdbd2cSJim Jagielski 
128*b1cdbd2cSJim Jagielski     /**
129*b1cdbd2cSJim Jagielski      * Set the tested interface and a log writer.
130*b1cdbd2cSJim Jagielski      * @param ifc The test of an interface
131*b1cdbd2cSJim Jagielski      * @param log A log writer.
132*b1cdbd2cSJim Jagielski      */
setTestedInterface(BasicIfcTest ifc, LogWriter log)133*b1cdbd2cSJim Jagielski     public void setTestedInterface(BasicIfcTest ifc, LogWriter log) {
134*b1cdbd2cSJim Jagielski         this.log = log;
135*b1cdbd2cSJim Jagielski         TestedInterface = ifc;
136*b1cdbd2cSJim Jagielski     }
137*b1cdbd2cSJim Jagielski 
138*b1cdbd2cSJim Jagielski     /**
139*b1cdbd2cSJim Jagielski      * Is called when BASIC signals that it has performed the test of a method.
140*b1cdbd2cSJim Jagielski      * @param methodName The name of the method.
141*b1cdbd2cSJim Jagielski      * @bResult The result of the test.
142*b1cdbd2cSJim Jagielski      */
methodTested(String methodName, boolean bResult)143*b1cdbd2cSJim Jagielski     synchronized void methodTested(String methodName, boolean bResult) {
144*b1cdbd2cSJim Jagielski         respFlag = true;
145*b1cdbd2cSJim Jagielski         TestedInterface.methodTested(methodName, bResult);
146*b1cdbd2cSJim Jagielski         notify() ;
147*b1cdbd2cSJim Jagielski     }
148*b1cdbd2cSJim Jagielski 
149*b1cdbd2cSJim Jagielski     /**
150*b1cdbd2cSJim Jagielski      * Is called when BASIC sends a signal to write some log information.
151*b1cdbd2cSJim Jagielski      * @param info The string to write.
152*b1cdbd2cSJim Jagielski      */
Log(String info)153*b1cdbd2cSJim Jagielski     synchronized public void Log(String info) {
154*b1cdbd2cSJim Jagielski         respFlag = true;
155*b1cdbd2cSJim Jagielski         log.println(info);
156*b1cdbd2cSJim Jagielski         notify() ;
157*b1cdbd2cSJim Jagielski     }
158*b1cdbd2cSJim Jagielski 
159*b1cdbd2cSJim Jagielski     /**
160*b1cdbd2cSJim Jagielski      * Is called by BasicIfcTest to find out if this BasicHandler uses the
161*b1cdbd2cSJim Jagielski      * correct MultiServiceFactory.
162*b1cdbd2cSJim Jagielski      * @param xMSF The MultiServiceFactory
163*b1cdbd2cSJim Jagielski      * @see com.sun.star.lang.XMultiServiceFactory
164*b1cdbd2cSJim Jagielski      * @return True, if xMSF is equal to the MultiServiceFactory of this class.
165*b1cdbd2cSJim Jagielski      */
isUptodate(XMultiServiceFactory xMSF)166*b1cdbd2cSJim Jagielski     public boolean isUptodate(XMultiServiceFactory xMSF) {
167*b1cdbd2cSJim Jagielski         return xMSF.equals(this.xMSF);
168*b1cdbd2cSJim Jagielski     }
169*b1cdbd2cSJim Jagielski 
170*b1cdbd2cSJim Jagielski 
171*b1cdbd2cSJim Jagielski     /**
172*b1cdbd2cSJim Jagielski      * Establishes a connection between BASIC and Java.
173*b1cdbd2cSJim Jagielski      * If required, hte BASIC part of the "driver" is loaded.
174*b1cdbd2cSJim Jagielski      * @param sBasicBridgeURL The URL of the basic bridge document
175*b1cdbd2cSJim Jagielski      *                                           (BasicBridge.sxw)
176*b1cdbd2cSJim Jagielski      * @param tParam The test parameters.
177*b1cdbd2cSJim Jagielski      * @param xMSF The MultiServiceFactory
178*b1cdbd2cSJim Jagielski      * @param log The log writer.
179*b1cdbd2cSJim Jagielski      * @see com.sun.star.lang.XMultiServiceFactory
180*b1cdbd2cSJim Jagielski      * @throws ConnectionSetupException Exception is thrown, if no connection could be made.
181*b1cdbd2cSJim Jagielski      */
Connect(String sBasicBridgeURL, TestParameters tParam, XMultiServiceFactory xMSF, LogWriter log)182*b1cdbd2cSJim Jagielski     public synchronized void Connect(String sBasicBridgeURL,
183*b1cdbd2cSJim Jagielski                             TestParameters tParam, XMultiServiceFactory xMSF,
184*b1cdbd2cSJim Jagielski                             LogWriter log) throws ConnectionSetupException {
185*b1cdbd2cSJim Jagielski         this.log = log;
186*b1cdbd2cSJim Jagielski         try {
187*b1cdbd2cSJim Jagielski             this.xMSF = xMSF;
188*b1cdbd2cSJim Jagielski             Object oInterface = xMSF.createInstance(
189*b1cdbd2cSJim Jagielski                                                 "com.sun.star.frame.Desktop");
190*b1cdbd2cSJim Jagielski             XDesktop oDesktop = (XDesktop) UnoRuntime.queryInterface(
191*b1cdbd2cSJim Jagielski                                                 XDesktop.class, oInterface);
192*b1cdbd2cSJim Jagielski             XComponentLoader oCLoader = (XComponentLoader)
193*b1cdbd2cSJim Jagielski                                         UnoRuntime.queryInterface(
194*b1cdbd2cSJim Jagielski                                         XComponentLoader.class, oDesktop);
195*b1cdbd2cSJim Jagielski 
196*b1cdbd2cSJim Jagielski             // load BasicBridge with MarcoEceutionMode = Always-no warn
197*b1cdbd2cSJim Jagielski             //PropertyValue[] DocArgs = null;
198*b1cdbd2cSJim Jagielski             PropertyValue[] DocArgs = new PropertyValue[1];
199*b1cdbd2cSJim Jagielski             PropertyValue DocArg = new PropertyValue();
200*b1cdbd2cSJim Jagielski             DocArg.Name = "MacroExecutionMode";
201*b1cdbd2cSJim Jagielski             DocArg.Value = new Short(
202*b1cdbd2cSJim Jagielski                     com.sun.star.document.MacroExecMode.ALWAYS_EXECUTE_NO_WARN);
203*b1cdbd2cSJim Jagielski             DocArgs[0] = DocArg;
204*b1cdbd2cSJim Jagielski 
205*b1cdbd2cSJim Jagielski             // configure Office to allow to execute macos
206*b1cdbd2cSJim Jagielski             PropertyValue [] ProvArgs = new PropertyValue [1];
207*b1cdbd2cSJim Jagielski             PropertyValue Arg = new PropertyValue();
208*b1cdbd2cSJim Jagielski             Arg.Name = "nodepath";
209*b1cdbd2cSJim Jagielski             Arg.Value = "/org.openoffice.Office.Common/Security";
210*b1cdbd2cSJim Jagielski             ProvArgs[0] = Arg;
211*b1cdbd2cSJim Jagielski 
212*b1cdbd2cSJim Jagielski             Object oProvider = xMSF.createInstance(
213*b1cdbd2cSJim Jagielski                         "com.sun.star.configuration.ConfigurationProvider");
214*b1cdbd2cSJim Jagielski 
215*b1cdbd2cSJim Jagielski             XMultiServiceFactory oProviderMSF = (XMultiServiceFactory)
216*b1cdbd2cSJim Jagielski                                     UnoRuntime.queryInterface(
217*b1cdbd2cSJim Jagielski                                     XMultiServiceFactory.class, oProvider);
218*b1cdbd2cSJim Jagielski 
219*b1cdbd2cSJim Jagielski             Object oSecure = oProviderMSF.createInstanceWithArguments(
220*b1cdbd2cSJim Jagielski                         "com.sun.star.configuration.ConfigurationUpdateAccess",
221*b1cdbd2cSJim Jagielski                         ProvArgs);
222*b1cdbd2cSJim Jagielski 
223*b1cdbd2cSJim Jagielski             XPropertySet oSecureProps = (XPropertySet)
224*b1cdbd2cSJim Jagielski                         UnoRuntime.queryInterface(XPropertySet.class, oSecure);
225*b1cdbd2cSJim Jagielski 
226*b1cdbd2cSJim Jagielski             Object oScripting = oSecureProps.getPropertyValue("Scripting");
227*b1cdbd2cSJim Jagielski             XPropertySet oScriptingSettings = (XPropertySet)
228*b1cdbd2cSJim Jagielski                     UnoRuntime.queryInterface(XPropertySet.class, oScripting);
229*b1cdbd2cSJim Jagielski 
230*b1cdbd2cSJim Jagielski             oScriptingSettings.setPropertyValue("Warning", Boolean.FALSE);
231*b1cdbd2cSJim Jagielski             oScriptingSettings.setPropertyValue("OfficeBasic", new Integer(2));
232*b1cdbd2cSJim Jagielski 
233*b1cdbd2cSJim Jagielski             XChangesBatch oSecureChange = (XChangesBatch)
234*b1cdbd2cSJim Jagielski                     UnoRuntime.queryInterface(XChangesBatch.class, oSecure);
235*b1cdbd2cSJim Jagielski             oSecureChange.commitChanges();
236*b1cdbd2cSJim Jagielski 
237*b1cdbd2cSJim Jagielski             // As we want to have some information about a debugFile
238*b1cdbd2cSJim Jagielski             // BEFORE connection is established
239*b1cdbd2cSJim Jagielski             // we pass the information about it in frame name.
240*b1cdbd2cSJim Jagielski             String sFrameName = (String)tParam.get(
241*b1cdbd2cSJim Jagielski                                                 "soapi.test.basic.debugFile");
242*b1cdbd2cSJim Jagielski             if (sFrameName == null) sFrameName = "BasicRunner";
243*b1cdbd2cSJim Jagielski 
244*b1cdbd2cSJim Jagielski             oHandlerDoc = oCLoader.loadComponentFromURL(sBasicBridgeURL,
245*b1cdbd2cSJim Jagielski                                                     sFrameName, 40, DocArgs);
246*b1cdbd2cSJim Jagielski 
247*b1cdbd2cSJim Jagielski             do {
248*b1cdbd2cSJim Jagielski                 respFlag = false ;
249*b1cdbd2cSJim Jagielski                 wait(10000); // waiting for basic response for 10 seconds.
250*b1cdbd2cSJim Jagielski             } while (respFlag && !container.hasByName("BASIC_Done")) ;
251*b1cdbd2cSJim Jagielski 
252*b1cdbd2cSJim Jagielski             if (!container.hasByName("BASIC_Done")) {
253*b1cdbd2cSJim Jagielski                 throw new ConnectionSetupException("Connection timed out.");
254*b1cdbd2cSJim Jagielski             }
255*b1cdbd2cSJim Jagielski         } catch (Exception e) {
256*b1cdbd2cSJim Jagielski             System.out.println("Exception: " + e.toString());
257*b1cdbd2cSJim Jagielski             throw new ConnectionSetupException();
258*b1cdbd2cSJim Jagielski         }
259*b1cdbd2cSJim Jagielski 
260*b1cdbd2cSJim Jagielski         log.println("Java-BASIC connection established!");
261*b1cdbd2cSJim Jagielski     }
262*b1cdbd2cSJim Jagielski 
263*b1cdbd2cSJim Jagielski     /**
264*b1cdbd2cSJim Jagielski      * Overloads perform(Strin fName, Object params) for convenience.
265*b1cdbd2cSJim Jagielski      * @return A proprty value as result.
266*b1cdbd2cSJim Jagielski      *
267*b1cdbd2cSJim Jagielski     public synchronized PropertyValue perform(String fName)
268*b1cdbd2cSJim Jagielski                                                         throws BasicException {
269*b1cdbd2cSJim Jagielski         return perform(fName, "");
270*b1cdbd2cSJim Jagielski     }
271*b1cdbd2cSJim Jagielski */
272*b1cdbd2cSJim Jagielski     /**
273*b1cdbd2cSJim Jagielski      * Perform a test of a method.
274*b1cdbd2cSJim Jagielski      * @param fName The name of the method to test.
275*b1cdbd2cSJim Jagielski      * @param params The test parameters.
276*b1cdbd2cSJim Jagielski      * @return A proprty value as result of the test.
277*b1cdbd2cSJim Jagielski      * @throws BasicException The method could not be executed.
278*b1cdbd2cSJim Jagielski      */
perform(String fName, Object params)279*b1cdbd2cSJim Jagielski     public synchronized PropertyValue perform(String fName, Object params)
280*b1cdbd2cSJim Jagielski                                                         throws BasicException {
281*b1cdbd2cSJim Jagielski         try {
282*b1cdbd2cSJim Jagielski             container.callBasicFunction(fName, params);
283*b1cdbd2cSJim Jagielski 
284*b1cdbd2cSJim Jagielski             do {
285*b1cdbd2cSJim Jagielski                 respFlag = false;
286*b1cdbd2cSJim Jagielski                 // waiting for basic response for iBasicTimeout milliseconds.
287*b1cdbd2cSJim Jagielski                 wait(iBasicTimeout);
288*b1cdbd2cSJim Jagielski             } while(respFlag && !container.hasByName("BASIC_Done"));
289*b1cdbd2cSJim Jagielski 
290*b1cdbd2cSJim Jagielski         } catch (InterruptedException e) {
291*b1cdbd2cSJim Jagielski             System.out.println("The operation " + fName + " was interrupted.");
292*b1cdbd2cSJim Jagielski         } catch (com.sun.star.lang.DisposedException de) {
293*b1cdbd2cSJim Jagielski             System.out.println("## Office is disposed");
294*b1cdbd2cSJim Jagielski         }
295*b1cdbd2cSJim Jagielski 
296*b1cdbd2cSJim Jagielski         if (!container.hasByName("BASIC_Done")) {
297*b1cdbd2cSJim Jagielski             System.out.println("Operation timed out.");
298*b1cdbd2cSJim Jagielski                 throw new BasicException(
299*b1cdbd2cSJim Jagielski                             "Operation timed out.");
300*b1cdbd2cSJim Jagielski         }
301*b1cdbd2cSJim Jagielski 
302*b1cdbd2cSJim Jagielski         Object res = container.getByName("BASIC_Done") ;
303*b1cdbd2cSJim Jagielski         container.removeByName("BASIC_Done");
304*b1cdbd2cSJim Jagielski 
305*b1cdbd2cSJim Jagielski         if (!(res instanceof PropertyValue)) {
306*b1cdbd2cSJim Jagielski             if (res == null) {
307*b1cdbd2cSJim Jagielski                 System.out.println(
308*b1cdbd2cSJim Jagielski                             "BasicBridge returns null");
309*b1cdbd2cSJim Jagielski                 throw new BasicException(
310*b1cdbd2cSJim Jagielski                             "BasicBridge returns null");
311*b1cdbd2cSJim Jagielski             } else {
312*b1cdbd2cSJim Jagielski                 System.out.println(
313*b1cdbd2cSJim Jagielski                             "BasicBridge returns wrong type: " + res.getClass());
314*b1cdbd2cSJim Jagielski                 throw new BasicException(
315*b1cdbd2cSJim Jagielski                             "BasicBridge returns wrong type: " + res.getClass());
316*b1cdbd2cSJim Jagielski             }
317*b1cdbd2cSJim Jagielski         }
318*b1cdbd2cSJim Jagielski 
319*b1cdbd2cSJim Jagielski         PropertyValue result = (PropertyValue) res ;
320*b1cdbd2cSJim Jagielski 
321*b1cdbd2cSJim Jagielski         if ((result.Value instanceof String) && (((String)result.Value)).startsWith("Exception")) {
322*b1cdbd2cSJim Jagielski             throw new BasicException((String)result.Value);
323*b1cdbd2cSJim Jagielski         }
324*b1cdbd2cSJim Jagielski 
325*b1cdbd2cSJim Jagielski         return result;
326*b1cdbd2cSJim Jagielski     }
327*b1cdbd2cSJim Jagielski 
328*b1cdbd2cSJim Jagielski     /**
329*b1cdbd2cSJim Jagielski      * Returns true, if name is a supported service of this class.
330*b1cdbd2cSJim Jagielski      * @param name The service name.
331*b1cdbd2cSJim Jagielski      * @return True, if the service is supported.
332*b1cdbd2cSJim Jagielski      */
supportsService(String name)333*b1cdbd2cSJim Jagielski     public boolean supportsService(String name) {
334*b1cdbd2cSJim Jagielski         return serviceName.equals(name);
335*b1cdbd2cSJim Jagielski     }
336*b1cdbd2cSJim Jagielski 
337*b1cdbd2cSJim Jagielski     /**
338*b1cdbd2cSJim Jagielski      * Return all supported service names.
339*b1cdbd2cSJim Jagielski      * @return All supported services.
340*b1cdbd2cSJim Jagielski      */
getSupportedServiceNames()341*b1cdbd2cSJim Jagielski     public String[] getSupportedServiceNames() {
342*b1cdbd2cSJim Jagielski         return new String[] {serviceName};
343*b1cdbd2cSJim Jagielski     }
344*b1cdbd2cSJim Jagielski 
345*b1cdbd2cSJim Jagielski     /**
346*b1cdbd2cSJim Jagielski      * Get the implementation name.
347*b1cdbd2cSJim Jagielski      * @return Implementation name.
348*b1cdbd2cSJim Jagielski      */
getImplementationName()349*b1cdbd2cSJim Jagielski     public String getImplementationName() {
350*b1cdbd2cSJim Jagielski         return getClass().getName();
351*b1cdbd2cSJim Jagielski     }
352*b1cdbd2cSJim Jagielski 
353*b1cdbd2cSJim Jagielski     /**
354*b1cdbd2cSJim Jagielski      * Create an instance of HandlerContainer.
355*b1cdbd2cSJim Jagielski      * Arguments are not supported here, so they will be ignored.
356*b1cdbd2cSJim Jagielski      * @param args The arguments.
357*b1cdbd2cSJim Jagielski      * @return The instance.
358*b1cdbd2cSJim Jagielski      */
createInstanceWithArguments(Object[] args)359*b1cdbd2cSJim Jagielski     public Object createInstanceWithArguments(Object[] args) {
360*b1cdbd2cSJim Jagielski         return container;
361*b1cdbd2cSJim Jagielski     }
362*b1cdbd2cSJim Jagielski 
363*b1cdbd2cSJim Jagielski     /**
364*b1cdbd2cSJim Jagielski      * Create an instance of HandlerContainer.
365*b1cdbd2cSJim Jagielski      * @return The instance.
366*b1cdbd2cSJim Jagielski      */
createInstance()367*b1cdbd2cSJim Jagielski     public Object createInstance() {
368*b1cdbd2cSJim Jagielski         return createInstanceWithArguments(null);
369*b1cdbd2cSJim Jagielski     }
370*b1cdbd2cSJim Jagielski 
371*b1cdbd2cSJim Jagielski     /**
372*b1cdbd2cSJim Jagielski      * Dispose the BASIC document.
373*b1cdbd2cSJim Jagielski      */
dispose()374*b1cdbd2cSJim Jagielski     public synchronized void dispose() {
375*b1cdbd2cSJim Jagielski         try {
376*b1cdbd2cSJim Jagielski             if (oHandlerDoc != null) {
377*b1cdbd2cSJim Jagielski                 //oHandlerDoc.dispose();
378*b1cdbd2cSJim Jagielski                 util.DesktopTools.closeDoc(oHandlerDoc);
379*b1cdbd2cSJim Jagielski                 wait(1000);
380*b1cdbd2cSJim Jagielski             }
381*b1cdbd2cSJim Jagielski         } catch (Exception e) {
382*b1cdbd2cSJim Jagielski             System.out.println("Exception: " + e.toString());
383*b1cdbd2cSJim Jagielski         }
384*b1cdbd2cSJim Jagielski     }
385*b1cdbd2cSJim Jagielski }
386*b1cdbd2cSJim Jagielski 
387*b1cdbd2cSJim Jagielski 
388*b1cdbd2cSJim Jagielski /**
389*b1cdbd2cSJim Jagielski  * This class handles the communication between Java and BASIC.
390*b1cdbd2cSJim Jagielski  * @see com.sun.star.container.XContainer
391*b1cdbd2cSJim Jagielski  * @see com.sun.star.container.XNameContainer
392*b1cdbd2cSJim Jagielski  * @see com.sun.star.lang.XTypeProvider
393*b1cdbd2cSJim Jagielski  */
394*b1cdbd2cSJim Jagielski class HandlerContainer implements XContainer, XNameContainer, XTypeProvider{
395*b1cdbd2cSJim Jagielski 
396*b1cdbd2cSJim Jagielski     /** Container for parameters.
397*b1cdbd2cSJim Jagielski      **/
398*b1cdbd2cSJim Jagielski     Hashtable container = new Hashtable(20);
399*b1cdbd2cSJim Jagielski     /**
400*b1cdbd2cSJim Jagielski      * An array of listeners for container events.
401*b1cdbd2cSJim Jagielski      * @see com.sun.star.container.XContainerListener
402*b1cdbd2cSJim Jagielski      */
403*b1cdbd2cSJim Jagielski     static XContainerListener[] listener = null;
404*b1cdbd2cSJim Jagielski 
405*b1cdbd2cSJim Jagielski     /** The BasicHandler belonging to this handler. **/
406*b1cdbd2cSJim Jagielski     BasicHandler parent = null;
407*b1cdbd2cSJim Jagielski 
408*b1cdbd2cSJim Jagielski     /**
409*b1cdbd2cSJim Jagielski      * Constructor with the parent BasicHandler.
410*b1cdbd2cSJim Jagielski      * @param par The BasicHandler.
411*b1cdbd2cSJim Jagielski      */
HandlerContainer(BasicHandler par)412*b1cdbd2cSJim Jagielski     public HandlerContainer(BasicHandler par) {
413*b1cdbd2cSJim Jagielski         parent = par;
414*b1cdbd2cSJim Jagielski     }
415*b1cdbd2cSJim Jagielski 
416*b1cdbd2cSJim Jagielski     /**
417*b1cdbd2cSJim Jagielski      * Call a BASIC function, meaning a test method.
418*b1cdbd2cSJim Jagielski      * @param fName The method name.
419*b1cdbd2cSJim Jagielski      * @param args Arguments for the method.
420*b1cdbd2cSJim Jagielski      */
callBasicFunction(String fName, Object args)421*b1cdbd2cSJim Jagielski     public void callBasicFunction(String fName, Object args) {
422*b1cdbd2cSJim Jagielski         // BASIC's listener should be called ONLY in this case.
423*b1cdbd2cSJim Jagielski         if (container.containsKey(fName)) {
424*b1cdbd2cSJim Jagielski             container.remove(fName);
425*b1cdbd2cSJim Jagielski         }
426*b1cdbd2cSJim Jagielski         container.put(fName, args);
427*b1cdbd2cSJim Jagielski         if (listener != null) {
428*b1cdbd2cSJim Jagielski             ContainerEvent event = new ContainerEvent();
429*b1cdbd2cSJim Jagielski             event.Element = fName;
430*b1cdbd2cSJim Jagielski             for (int i=0; i<listener.length; i++){
431*b1cdbd2cSJim Jagielski                 if (listener[i] != null) {
432*b1cdbd2cSJim Jagielski                     listener[i].elementInserted(event);
433*b1cdbd2cSJim Jagielski                 }
434*b1cdbd2cSJim Jagielski             }
435*b1cdbd2cSJim Jagielski         }
436*b1cdbd2cSJim Jagielski     }
437*b1cdbd2cSJim Jagielski 
438*b1cdbd2cSJim Jagielski     /**
439*b1cdbd2cSJim Jagielski      * Insert an object into the container.
440*b1cdbd2cSJim Jagielski      * @param name The key for the object.
441*b1cdbd2cSJim Jagielski      * @param object The object to insert.
442*b1cdbd2cSJim Jagielski      * @throws IllegalArgumentException Throws this exception when trying to insert null.
443*b1cdbd2cSJim Jagielski      */
insertByName(String name, Object object)444*b1cdbd2cSJim Jagielski     public void insertByName(String name, Object object) throws com.sun.star.lang.IllegalArgumentException, com.sun.star.container.ElementExistException, com.sun.star.lang.WrappedTargetException {
445*b1cdbd2cSJim Jagielski 
446*b1cdbd2cSJim Jagielski         // BASIC and Java can insert into the container.
447*b1cdbd2cSJim Jagielski         if (container.containsKey(name)) {
448*b1cdbd2cSJim Jagielski             container.remove(name);
449*b1cdbd2cSJim Jagielski         }
450*b1cdbd2cSJim Jagielski         container.put(name, object);
451*b1cdbd2cSJim Jagielski 
452*b1cdbd2cSJim Jagielski         PropertyValue result = null ;
453*b1cdbd2cSJim Jagielski 
454*b1cdbd2cSJim Jagielski         if (object instanceof PropertyValue) {
455*b1cdbd2cSJim Jagielski             result = (PropertyValue)object;
456*b1cdbd2cSJim Jagielski             if (name.equals("BASIC_Done")) {
457*b1cdbd2cSJim Jagielski                 synchronized (parent) {
458*b1cdbd2cSJim Jagielski                     parent.notify();
459*b1cdbd2cSJim Jagielski                 }
460*b1cdbd2cSJim Jagielski             } else if (name.equals("BASIC_MethodTested")) {
461*b1cdbd2cSJim Jagielski                 parent.methodTested(result.Name,
462*b1cdbd2cSJim Jagielski                                 ((Boolean)result.Value).booleanValue());
463*b1cdbd2cSJim Jagielski             }
464*b1cdbd2cSJim Jagielski         } else if (name.equals("BASIC_Log")) {
465*b1cdbd2cSJim Jagielski             parent.Log(object.toString());
466*b1cdbd2cSJim Jagielski         }
467*b1cdbd2cSJim Jagielski     }
468*b1cdbd2cSJim Jagielski 
469*b1cdbd2cSJim Jagielski     /**
470*b1cdbd2cSJim Jagielski      * Remove the object with this name from the container.
471*b1cdbd2cSJim Jagielski      * @param name The key.
472*b1cdbd2cSJim Jagielski      */
removeByName(String name)473*b1cdbd2cSJim Jagielski     public void removeByName(String name) {
474*b1cdbd2cSJim Jagielski         container.remove(name) ;
475*b1cdbd2cSJim Jagielski     }
476*b1cdbd2cSJim Jagielski 
477*b1cdbd2cSJim Jagielski     /**
478*b1cdbd2cSJim Jagielski      * Unsupported method.
479*b1cdbd2cSJim Jagielski      * @param name The name of the key.
480*b1cdbd2cSJim Jagielski      * @param value The value.
481*b1cdbd2cSJim Jagielski      * @throws WrappedTargetException Throws this exception when called falsely.
482*b1cdbd2cSJim Jagielski      */
replaceByName(String name, Object value)483*b1cdbd2cSJim Jagielski     public void replaceByName(String name, Object value)
484*b1cdbd2cSJim Jagielski                                           throws WrappedTargetException {
485*b1cdbd2cSJim Jagielski         throw new WrappedTargetException("Unsupported");
486*b1cdbd2cSJim Jagielski     }
487*b1cdbd2cSJim Jagielski 
488*b1cdbd2cSJim Jagielski     /**
489*b1cdbd2cSJim Jagielski      * Has a value for this key.
490*b1cdbd2cSJim Jagielski      * @param name The name of a key.
491*b1cdbd2cSJim Jagielski      * @return True, if name exists as key in the container.
492*b1cdbd2cSJim Jagielski      */
hasByName(String name)493*b1cdbd2cSJim Jagielski     public boolean hasByName(String name) {
494*b1cdbd2cSJim Jagielski         return container.containsKey(name);
495*b1cdbd2cSJim Jagielski     }
496*b1cdbd2cSJim Jagielski 
497*b1cdbd2cSJim Jagielski     /**
498*b1cdbd2cSJim Jagielski      * Get an object by its key.
499*b1cdbd2cSJim Jagielski      * @param name The name of the key.
500*b1cdbd2cSJim Jagielski      * @return The object of this key.
501*b1cdbd2cSJim Jagielski      */
getByName(String name)502*b1cdbd2cSJim Jagielski     public Object getByName(String name) {
503*b1cdbd2cSJim Jagielski         return container.get(name);
504*b1cdbd2cSJim Jagielski     }
505*b1cdbd2cSJim Jagielski 
506*b1cdbd2cSJim Jagielski     /**
507*b1cdbd2cSJim Jagielski      * Get all key names.
508*b1cdbd2cSJim Jagielski      * @return All names of keys.
509*b1cdbd2cSJim Jagielski      */
getElementNames()510*b1cdbd2cSJim Jagielski     public String[] getElementNames() {
511*b1cdbd2cSJim Jagielski         String[] res = new String[container.size()];
512*b1cdbd2cSJim Jagielski         return (String[])container.keySet().toArray(res);
513*b1cdbd2cSJim Jagielski     }
514*b1cdbd2cSJim Jagielski 
515*b1cdbd2cSJim Jagielski     /**
516*b1cdbd2cSJim Jagielski      * Is the xcontainer empty?
517*b1cdbd2cSJim Jagielski      * @return True, if the container has elements.
518*b1cdbd2cSJim Jagielski      */
hasElements()519*b1cdbd2cSJim Jagielski     public boolean hasElements() {
520*b1cdbd2cSJim Jagielski         return !container.isEmpty();
521*b1cdbd2cSJim Jagielski     }
522*b1cdbd2cSJim Jagielski 
523*b1cdbd2cSJim Jagielski     /**
524*b1cdbd2cSJim Jagielski      * Get the type of this class.
525*b1cdbd2cSJim Jagielski      * @return The type of this class.
526*b1cdbd2cSJim Jagielski      */
getElementType()527*b1cdbd2cSJim Jagielski     public Type getElementType() {
528*b1cdbd2cSJim Jagielski         try {
529*b1cdbd2cSJim Jagielski             return new Type(String.class);
530*b1cdbd2cSJim Jagielski         } catch (Exception e) {
531*b1cdbd2cSJim Jagielski             return null;
532*b1cdbd2cSJim Jagielski         }
533*b1cdbd2cSJim Jagielski     }
534*b1cdbd2cSJim Jagielski 
535*b1cdbd2cSJim Jagielski     /**
536*b1cdbd2cSJim Jagielski      * Get the implementation id of this class.
537*b1cdbd2cSJim Jagielski      * @return A unique id for this class
538*b1cdbd2cSJim Jagielski      * @see com.sun.star.lang.XTypeProvider
539*b1cdbd2cSJim Jagielski      */
getImplementationId()540*b1cdbd2cSJim Jagielski     public byte[] getImplementationId() {
541*b1cdbd2cSJim Jagielski         return toString().getBytes();
542*b1cdbd2cSJim Jagielski     }
543*b1cdbd2cSJim Jagielski 
544*b1cdbd2cSJim Jagielski     /**
545*b1cdbd2cSJim Jagielski      * Get all types of this class.
546*b1cdbd2cSJim Jagielski      * @return All implemented UNO types.
547*b1cdbd2cSJim Jagielski      */
getTypes()548*b1cdbd2cSJim Jagielski     public Type[] getTypes() {
549*b1cdbd2cSJim Jagielski         Class interfaces[] = getClass().getInterfaces();
550*b1cdbd2cSJim Jagielski         Type types[] = new Type[interfaces.length];
551*b1cdbd2cSJim Jagielski         for(int i = 0; i < interfaces.length; ++ i) {
552*b1cdbd2cSJim Jagielski             types[i] = new Type(interfaces[i]);
553*b1cdbd2cSJim Jagielski         }
554*b1cdbd2cSJim Jagielski         return types;
555*b1cdbd2cSJim Jagielski     }
556*b1cdbd2cSJim Jagielski 
557*b1cdbd2cSJim Jagielski     /**
558*b1cdbd2cSJim Jagielski      * Add a listener
559*b1cdbd2cSJim Jagielski      * @param xListener The listener.
560*b1cdbd2cSJim Jagielski      */
addContainerListener(XContainerListener xListener)561*b1cdbd2cSJim Jagielski     public void addContainerListener(XContainerListener xListener){
562*b1cdbd2cSJim Jagielski         int length = 0;
563*b1cdbd2cSJim Jagielski         if (listener != null)
564*b1cdbd2cSJim Jagielski             length = listener.length;
565*b1cdbd2cSJim Jagielski 
566*b1cdbd2cSJim Jagielski         XContainerListener[] mListener =
567*b1cdbd2cSJim Jagielski                         new XContainerListener[length+1];
568*b1cdbd2cSJim Jagielski         for (int i=0; i<length-1; i++) {
569*b1cdbd2cSJim Jagielski             mListener[i] = listener[i];
570*b1cdbd2cSJim Jagielski             // listener already added
571*b1cdbd2cSJim Jagielski             if (((Object)xListener).equals(listener[i]))
572*b1cdbd2cSJim Jagielski                 return;
573*b1cdbd2cSJim Jagielski         }
574*b1cdbd2cSJim Jagielski         mListener[length] = xListener;
575*b1cdbd2cSJim Jagielski         listener = mListener;
576*b1cdbd2cSJim Jagielski     }
577*b1cdbd2cSJim Jagielski 
578*b1cdbd2cSJim Jagielski     /**
579*b1cdbd2cSJim Jagielski      * Remove a listener
580*b1cdbd2cSJim Jagielski      * @param xListener The listener.
581*b1cdbd2cSJim Jagielski      */
removeContainerListener(XContainerListener xListener)582*b1cdbd2cSJim Jagielski     public void removeContainerListener(XContainerListener xListener){
583*b1cdbd2cSJim Jagielski         if (listener != null && listener.length != 0) {
584*b1cdbd2cSJim Jagielski             int length = listener.length;
585*b1cdbd2cSJim Jagielski             XContainerListener[] mListener =
586*b1cdbd2cSJim Jagielski                                     new XContainerListener[length-1];
587*b1cdbd2cSJim Jagielski             boolean found = false;
588*b1cdbd2cSJim Jagielski             int j=0;
589*b1cdbd2cSJim Jagielski             for (int i=0; i<length-1; i++) {
590*b1cdbd2cSJim Jagielski                 if (!((Object)xListener).equals(listener[j])) {
591*b1cdbd2cSJim Jagielski                     mListener[i] = listener[j];
592*b1cdbd2cSJim Jagielski                 }
593*b1cdbd2cSJim Jagielski                 else {
594*b1cdbd2cSJim Jagielski                     j++;
595*b1cdbd2cSJim Jagielski                     found = true;
596*b1cdbd2cSJim Jagielski                 }
597*b1cdbd2cSJim Jagielski                 j++;
598*b1cdbd2cSJim Jagielski             }
599*b1cdbd2cSJim Jagielski             if (!found) {
600*b1cdbd2cSJim Jagielski                 if (((Object)xListener).equals(listener[length-1]))
601*b1cdbd2cSJim Jagielski                     listener = mListener;
602*b1cdbd2cSJim Jagielski             }
603*b1cdbd2cSJim Jagielski             else
604*b1cdbd2cSJim Jagielski                 listener = mListener;
605*b1cdbd2cSJim Jagielski 
606*b1cdbd2cSJim Jagielski         }
607*b1cdbd2cSJim Jagielski     }
608*b1cdbd2cSJim Jagielski }
609