KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jac > aspects > gui > EventHandler


1 /*
2   Copyright (C) 2001-2003 Renaud Pawlak <renaud@aopsys.com>,
3                           Laurent Martelli <laurent@aopsys.com>
4
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU Lesser General Public License as
7   published by the Free Software Foundation; either version 2 of the
8   License, or (at your option) any later version.
9
10   This program is distributed in the hope that it will be useful, but
11   WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13   Lesser General Public License for more details.
14
15   You should have received a copy of the GNU Lesser General Public
16   License along with this program; if not, write to the Free Software
17   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18   USA */

19
20 package org.objectweb.jac.aspects.gui;
21
22 import java.util.Arrays JavaDoc;
23 import java.util.Collection JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.List JavaDoc;
26 import java.util.Map JavaDoc;
27 import java.util.Vector JavaDoc;
28 import org.apache.log4j.Logger;
29 import org.objectweb.jac.aspects.integrity.RoleWrapper;
30 import org.objectweb.jac.aspects.session.SessionAC;
31 import org.objectweb.jac.core.Collaboration;
32 import org.objectweb.jac.core.Interaction;
33 import org.objectweb.jac.core.ObjectRepository;
34 import org.objectweb.jac.core.Wrappee;
35 import org.objectweb.jac.core.Wrapping;
36 import org.objectweb.jac.core.rtti.AbstractMethodItem;
37 import org.objectweb.jac.core.rtti.ClassItem;
38 import org.objectweb.jac.core.rtti.ClassRepository;
39 import org.objectweb.jac.core.rtti.CollectionItem;
40 import org.objectweb.jac.core.rtti.FieldItem;
41 import org.objectweb.jac.core.rtti.MemberItem;
42 import org.objectweb.jac.core.rtti.MethodItem;
43 import org.objectweb.jac.core.rtti.NamingConventions;
44 import org.objectweb.jac.core.rtti.RttiAC;
45 import org.objectweb.jac.util.ExtArrays;
46 import org.objectweb.jac.util.Strings;
47
48 /**
49  * This handler manages events received from GUIs (web and swing for
50  * now). It is especially used for lists and arrays (onSelection,
51  * onView, etc ...)
52  */

53
54 public class EventHandler implements FieldUpdate {
55     static Logger logger = Logger.getLogger("gui.events");
56     static Logger loggerDnd = Logger.getLogger("gui.dnd");
57     static Logger loggerAssoc = Logger.getLogger("associations");
58
59     static EventHandler singleton = new EventHandler();
60
61     public static EventHandler get() {
62         return singleton;
63     }
64
65     /**
66      * Upcalled when a selection occurs on a field.
67      *
68      * @param context the context
69      * @param container ???
70      * @param selectedObject the selected object
71      * @param field ???
72      * @param extraOption */

73
74     public void onSelection(
75         DisplayContext context,
76         MemberItem container,
77         Object JavaDoc selectedObject,
78         FieldItem field,
79         Object JavaDoc extraOption)
80     {
81         onSelection(
82             context,
83             container,
84             selectedObject,
85             field,
86             extraOption,
87             false);
88     }
89
90     /**
91      * Upcalled when a view is asked on an object.
92      *
93      * @param context the context
94      * @param container ???
95      * @param selectedObject the selected object
96      * @param field ???
97      * @param extraOption */

98
99     public void onView(
100         DisplayContext context,
101         MemberItem container,
102         Object JavaDoc selectedObject,
103         FieldItem field,
104         Object JavaDoc extraOption)
105     {
106         onSelection(
107             context,
108             container,
109             selectedObject,
110             field,
111             extraOption,
112             true);
113     }
114
115     /**
116      * Upcalled when a selection occurs on a field. Displays a view of
117      * the selected object.
118      *
119      * @param context the context
120      * @param container member (reference, collection, or method) that
121      * references the selected object (the result in case of a method)
122      * @param selectedObject the selected object
123      * @param field give focus to this field in the view of the selected object
124      * @param extraOption
125      * @param forceView when true, a window containing the selected
126      * object is opened if we could not find a place where to put the
127      * new view.
128      */

129     public void onSelection(
130         DisplayContext context,
131         MemberItem container,
132         Object JavaDoc selectedObject,
133         FieldItem field,
134         Object JavaDoc extraOption,
135         boolean forceView)
136     {
137         logger.debug("onSelection("
138             + (container != null ? container.getLongName() : "null") + ","
139             + Strings.hex(selectedObject)
140             + ",field="+ (field != null ? field.getLongName() : "null")
141             + ",force=" + forceView + ")");
142         CustomizedDisplay display = context.getDisplay();
143         ViewFactory factory = display.getFactory();
144         CustomizedView customizedView = context.getCustomizedView();
145
146         Collaboration.get().addAttribute(GuiAC.DISPLAY_CONTEXT, context);
147
148         // in choice view collections, nothing as to be done except a refresh
149
if (container instanceof CollectionItem) {
150             if (GuiAC.isChoiceView((CollectionItem) container)
151                 && !GuiAC.isExternalChoiceView((CollectionItem) container)) {
152                 display.refresh();
153                 return;
154             }
155         }
156
157         MethodItem handler = null;
158         FieldItem targetField = null;
159         if (container != null) {
160             handler = GuiAC.getSelectionHandler(container);
161             targetField =
162                 (FieldItem) container.getAttribute(GuiAC.SELECTION_TARGET);
163         }
164
165         if (customizedView == null && handler == null && targetField == null) {
166             if (forceView) {
167                 logger.debug("showing in dialog mode " + "(customizedView==null)");
168                 display.show(selectedObject);
169             } else {
170                 logger.debug("onSelection aborted " + "(customizedView==null)");
171                 display.refresh();
172             }
173             return;
174         }
175
176         if (handler != null) {
177             try {
178                 logger.debug("invoking selectionHandler " + handler);
179                 Object JavaDoc result =
180                     handler.invokeStatic(
181                         new Object JavaDoc[] { context, container, selectedObject });
182                 if (handler.getType() != void.class && result != null) {
183                     if (handler.getType() == HandlerResult.class) {
184                         handleResult(context,(HandlerResult)result);
185                     } else {
186                         onSelection(context, null, result, null, null);
187                     }
188                 }
189             } catch (Exception JavaDoc e) {
190                 logger.error(
191                     "gui: invocation of event handler " + handler
192                     + " for onSelection failed with " + e);
193                 e.printStackTrace();
194             }
195         }
196
197         if (targetField != null) {
198             selectedObject = targetField.getThroughAccessor(selectedObject);
199             logger.debug("selected target -> " + selectedObject);
200         }
201
202         if (customizedView == null)
203             return;
204         CustomizedGUI customized = customizedView.getCustomizedGUI();
205         List JavaDoc targets = customized.getFieldTargets(container);
206         logger.debug("targets=" + targets);
207
208         if (targets != null) {
209             Iterator JavaDoc it = targets.iterator();
210             while (it.hasNext()) {
211                 // the target is a panelPath=
212
Target target = (Target) it.next();
213                 logger.debug("target.path = " + target.panePath);
214                 /*
215                                   // target.panePath must look like this <customizedId>/<paneId>
216                                   int index = target.panePath.indexOf("/");
217                                   if (index==-1) {
218                                   throw new RuntimeException("Bad pane path : "+target.panePath);
219                                   }
220                                   String customizedId = target.panePath.substring(0,index);
221                                   String paneId = target.panePath.substring(index+1);
222                                   logger.debug("customized = "+customizedId);
223                 */

224
225                 String JavaDoc paneId = target.panePath;
226                 CompositeView targetView =
227                     (CompositeView) customizedView.getView(paneId);
228
229                 if (selectedObject != null) {
230
231                     Collaboration.get().addAttribute(
232                         GuiAC.SMALL_VIEW,
233                         container.getAttribute(GuiAC.SMALL_TARGET_CONTAINER));
234                     try {
235                         // creating and adding the new view
236
View view =
237                             invalidatePane(
238                                 factory,
239                                 context,
240                                 targetView,
241                                 target.viewType,
242                                 target.viewParams,
243                                 selectedObject,
244                                 extraOption);
245
246                         if (field != null && view != null)
247                             setFocus(view, field, extraOption);
248
249                     } finally {
250                         Collaboration.get().removeAttribute(GuiAC.SMALL_VIEW);
251                     }
252                 }
253                 //targetView.validate();
254
maybeInvalidatePane(factory, context, customizedView, paneId);
255             }
256             display.refresh();
257         } else if (forceView) {
258             if (container != null
259                 && container.getAttribute(GuiAC.NEW_WINDOW) != null) {
260                 display.openView(selectedObject);
261             } else {
262                 display.show(selectedObject);
263             }
264         }
265
266     }
267
268     public void handleResult(DisplayContext context, HandlerResult hres) {
269         CustomizedView customizedView = context.getCustomizedView();
270         CustomizedDisplay display = context.getDisplay();
271         DisplayContext newContext =
272             new DisplayContext(
273                 display,
274                 hres.target != null
275                 ? hres.target
276                 : customizedView);
277         if (hres.target != null)
278             customizedView = hres.target;
279         onSelection(
280             newContext,
281             (CollectionItem) hres.container,
282             hres.object,
283             hres.field,
284             hres.extraOption);
285     }
286
287     /**
288      * Removes the content of pane when another pane's content is
289      * changed
290      *
291      * @param selectedPaneID ID of the selected pane */

292     public void maybeInvalidatePane(
293         ViewFactory factory,
294         DisplayContext context,
295         CustomizedView customizedView,
296         String JavaDoc selectedPaneID)
297     {
298         CustomizedGUI customized = customizedView.getCustomizedGUI();
299         String JavaDoc invalidPaneID = customized.getInvalidPane(selectedPaneID);
300         logger.debug("invalidPane " + selectedPaneID + " -> " + invalidPaneID);
301         if (invalidPaneID != null) {
302             invalidatePane(
303                 factory,
304                 context,
305                 (CompositeView) customizedView.getView(invalidPaneID),
306                 "Empty",
307                 ExtArrays.emptyStringArray,
308                 null,
309                 null);
310         }
311     }
312
313     /**
314      * Gives focus to the view which is a field editor for a given field.
315      * @param top view to start searching from. All subviews of this
316      * view will be recursively inspected.
317      * @param field the field whose editor to search for
318      * @param option an option that will be passed when calling
319      * <code>onSetFocus()</code> on the FieldEditor.
320      * @see FieldEditor#onSetFocus(Object)
321      */

322     public void setFocus(View top, FieldItem field, Object JavaDoc option) {
323         logger.debug("setFocus " + top + "," + field.getLongName() + "," + option);
324         if (top instanceof CompositeView) {
325             Iterator JavaDoc it = ((CompositeView) top).getViews().iterator();
326             while (it.hasNext()) {
327                 View view = (View) it.next();
328                 if (view instanceof TabsView) {
329                     String JavaDoc[] categories = GuiAC.getCategories(field);
330                     if (categories != null && categories.length > 0) {
331                         ((TabsView) view).select(categories[0]);
332                         setFocus(
333                             ((CompositeView) view).getView(categories[0]),
334                             field,
335                             option);
336                     }
337                 } else {
338                     setFocus(view, field, option);
339                 }
340             }
341         } else if (top instanceof FieldEditor) {
342             FieldEditor editor = (FieldEditor) top;
343             if (editor.getField().equals(field)) {
344                 editor.getContext().getCustomizedView().requestFocus();
345                 editor.onSetFocus(option);
346             }
347         }
348     }
349
350     /**
351      * Used only to test if a CompositeView contains the view that we
352      * are about to build.
353      */

354     /*
355       static class DummyView {
356       String type;
357       public void setType(String type) {
358       this.type = type;
359       }
360       public String getType() {
361       return type;
362       }
363
364       Object[] parameters;
365       public void setParameters(Object[] parameters) {
366       this.parameters = parameters;
367       }
368       public Object[] getParameters() {
369       return parameters;
370       }
371       public boolean equals(Object o) {
372       return o instanceof ViewIdentity
373       && ((ViewIdentity) o).getType().equals(type)
374       && Arrays.equals(((ViewIdentity) o).getParameters(), parameters);
375       }
376       public int hashCode() {
377       return type.hashCode() ^ parameters.hashCode();
378       }
379
380       public DummyView(String type, Object[] parameters) {
381       this.type = type;
382       this.parameters = parameters;
383       }
384       }
385     */

386
387     /**
388      * Create a view for an object and display it if it is not already
389      * displayed.
390      *
391      * @return the new view or the old one
392      */

393     View invalidatePane(
394         ViewFactory factory,
395         DisplayContext context,
396         CompositeView panel,
397         String JavaDoc viewType,
398         String JavaDoc[] viewParams,
399         Object JavaDoc selectedObject,
400         Object JavaDoc extraInfo)
401     {
402         logger.debug("invalidatePane("+panel+","
403             +viewType+Arrays.asList(viewParams)+ ","+selectedObject+")");
404         Collection JavaDoc comps = panel.getViews();
405         View view = null;
406         // close and remove the currently opened view in the panel
407
Object JavaDoc[] parameters;
408         if (selectedObject != null) {
409             parameters = ExtArrays.add(selectedObject, viewParams);
410         } else {
411             parameters = viewParams;
412         }
413         if (!panel.containsView(viewType, parameters)) {
414             logger.debug("new view " + viewType + ", extraInfo=" + extraInfo);
415             view =
416                 factory.createView(
417                     "target[?]",
418                     viewType,
419                     parameters,
420                     context);
421             if (extraInfo instanceof CollectionPosition &&
422                 GuiAC.hasSetNavBar(
423                     context.getCustomizedView().getCustomizedGUI(),
424                     ((CollectionPosition)extraInfo).getCollection()))
425             {
426                 view.setParentView(
427                     view =
428                     factory.createView(
429                         "collectionItemView",
430                         "CollectionItemView",
431                         new Object JavaDoc[] {
432                             view,
433                             extraInfo,
434                             viewType,
435                             viewParams,
436                             null },
437                         context));
438             }
439             logger.debug("new view CREATED");
440             panel.addView(view, GuiAC.toString(selectedObject));
441
442         } else {
443             Iterator JavaDoc i = comps.iterator();
444             while (i.hasNext()) {
445                 view = (View) i.next();
446                 if (view.equalsView(viewType,parameters)) {
447                     return view;
448                 }
449             }
450             return null;
451         }
452
453         return view;
454     }
455
456     /**
457      * Initialize an autocreated object by setting
458      */

459     public static void initAutocreatedObject(
460         Object JavaDoc created,
461         Object JavaDoc substance,
462         FieldItem role)
463     {
464         FieldItem oppositeRole =
465             (FieldItem) role.getAttribute(RttiAC.OPPOSITE_ROLE);
466         logger.debug("oppositeRole = " + oppositeRole);
467         if (oppositeRole != null) {
468             RoleWrapper.disableRoleUpdate(oppositeRole);
469             try {
470                 if (oppositeRole instanceof CollectionItem) {
471                     ((CollectionItem) oppositeRole).addThroughAdder(
472                         created,
473                         substance);
474                 } else {
475                     oppositeRole.setThroughWriter(created, substance);
476                 }
477             } catch (Exception JavaDoc e) {
478                 logger.error(
479                     "initAutocreatedObject(created=" + created
480                     + ",substance=" + substance
481                     + "role=" + role
482                     + "): " + e);
483             } finally {
484                 RoleWrapper.enableRoleUpdate(oppositeRole);
485             }
486         }
487     }
488
489     /**
490      * Upcalled when a tree node is selected.
491      *
492      * @param context the display context
493      * @param node the selected tree node
494      * @param forceView if true, the subtance of the node is opened in
495      * a new window
496      */

497     public void onNodeSelection(
498         DisplayContext context,
499         AbstractNode node,
500         boolean forceView)
501     {
502         logger.debug("onNodeSelection " + node);
503         AbstractNode parentNode = (AbstractNode) node.getParent();
504         if (parentNode != null) {
505             // recursively send the event for the parent nodes
506
onNodeSelection(context, parentNode, false);
507         }
508         if (node instanceof ObjectNode) {
509             onSelection(
510                 context,
511                 ((ObjectNode) node).getRelation(),
512                 node.getUserObject(),
513                 null,
514                 null,
515                 forceView);
516         } else if (node instanceof RootNode) {
517             onSelection(
518                 context,
519                 null,
520                 node.getUserObject(),
521                 null,
522                 null,
523                 forceView);
524         }
525     }
526
527     /**
528      * Upcalled when a direct invocation is performed on an object (no
529      * parameters will be asked by the GUI).
530      *
531      * @param context the display context
532      * @param substance the object that holds the method
533      * @param method the method to invoke
534      * @param parameters the parameters of the method
535      */

536     public void onInvokeDirect(
537         DisplayContext context,
538         Object JavaDoc substance,
539         AbstractMethodItem method,
540         Object JavaDoc[] parameters)
541     {
542         Collaboration.get().addAttribute(GuiAC.DISPLAY_CONTEXT, context);
543         method.invoke(substance, parameters);
544     }
545
546     /**
547      * Upcalled when an invocation is performed on an object.
548      *
549      * @param context the display context
550      * @param invoke
551      * @return the thread the method was invoked in
552      *
553      * @see #onInvoke(DisplayContext,InvokeEvent,String[],Object[])
554      * @see #onInvoke(DisplayContext,InvokeEvent,boolean,String[],Object[])
555      */

556     public InvokeThread onInvoke(
557         DisplayContext context,
558         InvokeEvent invoke)
559     {
560         return onInvoke(context, invoke, null, null);
561     }
562
563     /**
564      * Upcalled when an invocation is performed on an object.
565      *
566      * @param context the display context
567      * @param invoke
568      * @param attrNames the contextual attributes names to pass
569      * @param attrValues the contextual attributes values
570      * @return the thread the method was invoked in
571      *
572      * @see #onInvoke(DisplayContext,InvokeEvent)
573      * @see #onInvoke(DisplayContext,InvokeEvent,boolean,String[],Object[])
574      */

575     public InvokeThread onInvoke(
576         DisplayContext context,
577         InvokeEvent invoke,
578         String JavaDoc[] attrNames,
579         Object JavaDoc[] attrValues)
580     {
581         return onInvoke(context, invoke, true, attrNames, attrValues);
582     }
583
584     /**
585      * Invoke a method in the general case. Sets the necessary
586      * attributes in the context. The method is invoked in a new
587      * thread.
588      *
589      * @param context the display context
590      * @param invoke
591      * @param attrNames the contextual attributes names to pass
592      * @param attrValues the contextual attributes values
593      * @return the thread the method was invoked in
594      *
595      * @see #onInvoke(DisplayContext,InvokeEvent)
596      * @see #onInvoke(DisplayContext,InvokeEvent,String[],Object[])
597      */

598     public InvokeThread onInvoke(
599         DisplayContext context,
600         InvokeEvent invoke,
601         boolean askFormParameters,
602         String JavaDoc[] attrNames,
603         Object JavaDoc[] attrValues)
604     {
605         logger.debug("onInvoke(" + context + "," + invoke + ")");
606         CustomizedDisplay display = context.getDisplay();
607         if (attrNames == null)
608             attrNames = ExtArrays.emptyStringArray;
609         if (attrValues == null)
610             attrValues = ExtArrays.emptyStringArray;
611         Class JavaDoc[] parameterTypes = invoke.getMethod().getParameterTypes();
612         int parametersLeft = parameterTypes.length;
613         Object JavaDoc[] parameters = invoke.getParameters();
614         if (parameters == null) {
615             parameters = new Object JavaDoc[parameterTypes.length];
616         } else if (parameters.length < parameterTypes.length) {
617             // If there are not enough parameters,
618
// we assume the first ones are missing
619
parametersLeft -= parameters.length;
620             Object JavaDoc[] tmp = new Object JavaDoc[parameterTypes.length];
621             System.arraycopy(
622                 parameters,
623                 0,
624                 tmp,
625                 parameterTypes.length - parameters.length,
626                 parameters.length);
627             parameters = tmp;
628         }
629         if (parameters.length > 0
630             && parameterTypes[0] == DisplayContext.class) {
631             parametersLeft--;
632             parameters[0] = context;
633         }
634         invoke.setParameters(parameters);
635         // Get the session id from the current context
636
Object JavaDoc sid = Collaboration.get().getAttribute(SessionAC.SESSION_ID);
637         if (parametersLeft == 0) {
638             logger.debug("Invoking " + invoke);
639             String JavaDoc[] names = new String JavaDoc[2 + attrNames.length];
640             Object JavaDoc[] values = new Object JavaDoc[2 + attrNames.length];
641             names[0] = GuiAC.DISPLAY_CONTEXT;
642             values[0] = context;
643             names[1] = SessionAC.SESSION_ID;
644             values[1] = sid;
645             System.arraycopy(attrNames, 0, names, 2, attrNames.length);
646             System.arraycopy(attrValues, 0, values, 2, attrNames.length);
647             return
648                 InvokeThread.run(
649                     invoke,
650                     null,
651                     null,
652                     names,
653                     values);
654         } else {
655             //new CallingBox( this, substance, method );
656
logger.debug("Invoking " + invoke +
657                 " (ask for parameters is on, "
658                 + parametersLeft + " parameters left)");
659
660             String JavaDoc[] names = new String JavaDoc[4 + attrNames.length];
661             Object JavaDoc[] values = new Object JavaDoc[4 + attrNames.length];
662             names[0] = GuiAC.DISPLAY_CONTEXT;
663             values[0] = context;
664             names[1] = SessionAC.SESSION_ID;
665             values[1] = sid;
666             names[2] = GuiAC.ASK_FOR_PARAMETERS;
667             names[3] = GuiAC.INVOKED_METHOD;
668             // Do not ask for parameters if all values are not null
669
if (ExtArrays.indexOf(parameters, null) != -1 && askFormParameters) {
670                 values[2] = invoke.getMethod().getConcreteMethod();
671                 values[3] = invoke.getMethod();
672             }
673
674             System.arraycopy(attrNames, 0, names, 4, attrNames.length);
675             System.arraycopy(attrValues, 0, values, 4, attrNames.length);
676             return
677                 InvokeThread.run(
678                     invoke,
679                     null,
680                     null,
681                     names,
682                     values);
683         }
684     }
685
686     /**
687      * Invoke a method and waits for the result (and returns it).
688      *
689      * @param context the display context
690      * @param invoke the method invocation to perform
691      */

692     public Object JavaDoc onInvokeSynchronous(
693         DisplayContext context,
694         InvokeEvent invoke)
695     {
696         logger.debug("onInvokeSynchronous(" + context + "," + invoke + ")");
697         CustomizedDisplay display = context.getDisplay();
698         Class JavaDoc[] parameterTypes = invoke.getMethod().getParameterTypes();
699         int parametersLeft = parameterTypes.length;
700         Object JavaDoc[] parameters = invoke.getParameters();
701         if (parameters == null) {
702             parameters = new Object JavaDoc[parameterTypes.length];
703         } else if (parameters.length < parameterTypes.length) {
704             // If there are not enough parameters,
705
// we assume the first ones are missing
706
parametersLeft -= parameters.length;
707             Object JavaDoc[] tmp = new Object JavaDoc[parameterTypes.length];
708             System.arraycopy(
709                 parameters,
710                 0,
711                 tmp,
712                 parameterTypes.length - parameters.length,
713                 parameters.length);
714             parameters = tmp;
715         }
716         if (parameters.length > 0
717             && parameterTypes[0] == DisplayContext.class) {
718             parametersLeft--;
719             parameters[0] = context;
720         }
721
722         String JavaDoc[] names;
723         Object JavaDoc[] values;
724
725         // Get the session id from the current context
726
Object JavaDoc sid = Collaboration.get().getAttribute(SessionAC.SESSION_ID);
727         if (parametersLeft == 0) {
728             logger.debug("Invoking " + invoke);
729             names =
730                 new String JavaDoc[] { GuiAC.DISPLAY_CONTEXT, SessionAC.SESSION_ID };
731             values = new Object JavaDoc[] { context, sid };
732         } else {
733             //new CallingBox( this, substance, method );
734
logger.debug("Invoking " + invoke
735                 + " (ask for parameters is on, "
736                 + parametersLeft + " parameters left)");
737             names =
738                 new String JavaDoc[] {
739                     GuiAC.DISPLAY_CONTEXT,
740                     SessionAC.SESSION_ID,
741                     GuiAC.ASK_FOR_PARAMETERS };
742             values = new Object JavaDoc[] { context, sid, invoke.getMethod() };
743         }
744
745         invoke.setParameters(parameters);
746         InvokeThread thread =
747             new InvokeThread(
748                 invoke,
749                 null,
750                 null,
751                 names,
752                 values);
753         thread.start();
754         return thread.getReturnValue();
755     }
7