001    /*
002      Copyright (C) 2001-2003 Renaud Pawlak <renaud@aopsys.com>, 
003                              Laurent Martelli <laurent@aopsys.com>
004    
005      This program is free software; you can redistribute it and/or modify
006      it under the terms of the GNU Lesser General Public License as
007      published by the Free Software Foundation; either version 2 of the
008      License, or (at your option) any later version.
009    
010      This program is distributed in the hope that it will be useful,
011      but WITHOUT ANY WARRANTY; without even the implied warranty of
012      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013      GNU Lesser General Public License for more details.
014    
015      You should have received a copy of the GNU Lesser General Public License
016      along with this program; if not, write to the Free Software
017      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
018    
019    package org.objectweb.jac.aspects.gui.web;
020    
021    import java.io.IOException;
022    import java.io.Writer;
023    import java.util.EmptyStackException;
024    import java.util.HashMap;
025    import java.util.Hashtable;
026    import java.util.Map;
027    import javax.servlet.ServletException;
028    import javax.servlet.ServletException;
029    import javax.servlet.http.HttpServlet;
030    import javax.servlet.http.HttpServletRequest;
031    import javax.servlet.http.HttpServletResponse;
032    import javax.servlet.http.HttpSession;
033    import org.apache.log4j.LogManager;
034    import org.apache.log4j.Logger;
035    import org.mortbay.util.MultiMap;
036    import org.mortbay.util.UrlEncoded;
037    import org.objectweb.jac.aspects.gui.CustomizedGUI;
038    import org.objectweb.jac.aspects.gui.DisplayContext;
039    import org.objectweb.jac.aspects.gui.EventHandler;
040    import org.objectweb.jac.aspects.gui.GuiAC;
041    import org.objectweb.jac.aspects.gui.InvokeEvent;
042    import org.objectweb.jac.aspects.gui.PanelContent;
043    import org.objectweb.jac.aspects.gui.TableCellViewer;
044    import org.objectweb.jac.aspects.gui.View;
045    import org.objectweb.jac.aspects.session.SessionAC;
046    import org.objectweb.jac.core.Collaboration;
047    import org.objectweb.jac.core.NameRepository;
048    import org.objectweb.jac.core.rtti.ClassRepository;
049    import org.objectweb.jac.core.rtti.MethodItem;
050    import org.objectweb.jac.util.ExtArrays;
051    import org.objectweb.jac.util.Strings;
052    import org.objectweb.jac.util.WrappedThrowableException;
053    
054    /**
055     * This servlet does the same thing as the JacServlet, but it does not
056     * use RMI. It is meant to be used with the integrated http server
057     * (Jetty).
058     */
059    
060    public class JacLocalServlet extends HttpServlet {
061        static final Logger logger = Logger.getLogger("web.servlet");
062        static final Logger loggerEvents = Logger.getLogger("gui.events");
063        static final Logger loggerPerf = Logger.getLogger("perf");
064        static final Logger loggerThreads = Logger.getLogger("threads");
065    
066        // SessionID -> WebDisplay
067        Hashtable displays = new Hashtable();
068    
069        // list of possible events
070        static Hashtable eventList = new Hashtable();
071        static {
072            eventList.put("onDirectInvoke", new Integer(1));
073            eventList.put("onView", new Integer(2));
074            eventList.put("onTableInvoke", new Integer(3));
075            eventList.put("onSelect", new Integer(4));
076            eventList.put("onInvoke", new Integer(5));
077            eventList.put("onSelection", new Integer(6));
078            eventList.put("onCellSelection", new Integer(7));
079            eventList.put("onHeaderClick", new Integer(8));
080            eventList.put("onClose", new Integer(9));
081            eventList.put("onValidate", new Integer(10));
082            eventList.put("onOK", new Integer(11));
083            eventList.put("onCancel", new Integer(12));
084            eventList.put("onAddToCollection", new Integer(13));
085            eventList.put("onRemoveFromCollection", new Integer(14));
086            eventList.put("onNext", new Integer(15));
087            eventList.put("onPrevious", new Integer(16));
088            eventList.put("onSelectNode", new Integer(17));
089            eventList.put("onExpandNode", new Integer(18));
090            eventList.put("onCollapseNode", new Integer(19));
091            eventList.put("onMenuClick", new Integer(20));
092            eventList.put("onCreateObject", new Integer(21));
093            eventList.put("onLoadAttachment", new Integer(22));
094            eventList.put("onPreviousInCollection", new Integer(23));
095            eventList.put("onNextInCollection", new Integer(24));
096            eventList.put("onBackToCollection", new Integer(25));
097            eventList.put("onRemoveInCollection", new Integer(26));
098            eventList.put("onRemove", new Integer(27));
099            eventList.put("onFirst", new Integer(28));
100            eventList.put("onLast", new Integer(29));
101            eventList.put("onAddEmbedded", new Integer(30));
102            eventList.put("onAddExistingToCollection", new Integer(31));
103            eventList.put("onSetDefaults", new Integer(32));
104            eventList.put("onViewObject", new Integer(33));
105            eventList.put("onRefresh", new Integer(34));
106            eventList.put("onRefreshCollection", new Integer(35));
107        }
108    
109        public JacLocalServlet() {
110        }
111    
112        public void doPost(
113            HttpServletRequest request,
114            HttpServletResponse response)
115            throws IOException, ServletException 
116        {
117            doGet(request, response);
118        }
119    
120        public void doGet(HttpServletRequest request, HttpServletResponse response)
121            throws IOException, ServletException 
122        {
123            //ejp.tracer.TracerAPI.enableTracing();
124    
125            logger.info("query -> "
126                        + request.getQueryString() + " -> " + Strings.hex(response));
127            logger.debug("request -> " + request);
128    
129            long start = System.currentTimeMillis();
130    
131            Collaboration.get().reset();
132            HttpSession session = request.getSession(true);
133            String sid = session.getId();
134    
135            String encoding = GuiAC.getEncoding();
136            if (request.getCharacterEncoding()==null) {
137                logger.info("Setting character encoding to "+encoding);
138                request.setCharacterEncoding(encoding);
139            }
140    
141            response.setContentType("text/html; charset="+encoding);
142            response.setHeader("Cache-Control", "no-cache");
143    
144            String contentType = request.getHeader("Content-type");
145            JacRequest jacRequest;
146            if (contentType != null
147                && contentType.startsWith("multipart/form-data")) {
148                MultiPartRequest parts = new MultiPartRequest(request,encoding);
149                jacRequest = new MultiPartJacRequest(parts, request);
150            } else {
151                jacRequest = new MultiMapJacRequest(request);
152            }
153    
154            String guiID = request.getServletPath().substring(1);
155    
156            WebDisplay display = (WebDisplay) displays.get(sid+":"+guiID);
157            if (display == null) {
158                logger.info("new Display for session " + sid);
159                display = new WebDisplay(GuiAC.getViewFactory("web"), sid);
160                display.setServletName(guiID);
161                displays.put(sid+":"+guiID, display);
162            }
163            logger.info(sid + " -> " + display);
164            WebDisplay.setResponse(response);
165            WebDisplay.setRequest(jacRequest);
166    
167            String event = (String) jacRequest.getParameter("event");
168            String eventAndAction =
169                (String) jacRequest.getParameter("eventAndAction");
170            if (eventAndAction != null) {
171                MultiMap params = new MultiMap();
172                logger.debug("eventAndAction = " + eventAndAction);
173                UrlEncoded.decodeTo(eventAndAction, params);
174                logger.debug("params = " + params);
175    
176                String source = (String) jacRequest.getParameter("source");
177                View dest = null;
178                if (source == null) {
179                    source = (String)params.get("source");
180                    dest = display.getView(source);
181                    if (dest == null) {
182                        error(display, jacRequest, "ERROR: no such view "+source);
183                        return;
184                    }
185                    Object window = dest.getContext().getWindow();
186                    if (!(window instanceof WindowListener)) {
187                        logger.warn("Window of "+source+" is not a WindowListener ("+window+")");
188                        dest = null;
189                    } else {
190                        dest = (View)window;
191                    }
192                } else {
193                    if (source.equals(params.get("source"))) {
194                        // In this case, the action will do the validationx
195                        logger.debug("Skipping onValidate for "+source);
196                    } else {
197                        dest = display.getView(source);
198                        if (dest == null) {
199                            error(display, jacRequest, "ERROR: no such view "+source);
200                            return;
201                        }
202                    }
203                }
204    
205                if (dest != null) {
206                    logger.info("event = onValidate -> " + dest + "(" + source + ")");
207                    try {
208                        loggerEvents.debug(dest+".onCancel");
209                        ((WindowListener)dest).onValidate(jacRequest);
210                    } catch(Exception e) {
211                        logger.error("Dialog validation failed for "+dest,e);
212                    }
213                } else {
214                    logger.info("No source for eventAndAction");
215                }
216                jacRequest = new MultiMapJacRequest(params, request, jacRequest); 
217                WebDisplay.setRequest(jacRequest);
218                handleEvent(
219                    jacRequest,
220                    response,
221                    display,
222                    sid,
223                    guiID,
224                    GuiAC.getCustomized(guiID));
225            } else {
226                CustomizedGUI cgui = GuiAC.getCustomized(guiID);
227                if (event == null) {
228                    logger.info("No event, looking for generic action");
229                    logger.info("  request="+jacRequest);                
230                    if (jacRequest.contains("showObject")) {
231                        logger.info("  showObject");                
232                        String name = // name of object to display
233                            (String)jacRequest.getParameter("object");
234                        if (name == null) {
235                            error(display, jacRequest,
236                                  "PROTOCOL ERROR: missing object argument for showObject");
237                        } else {
238                            Object object = NameRepository.get().getObject(name);
239                            String viewName = (String)jacRequest.getParameter("viewName");
240                            if (viewName!=null) {
241                                display.show(object,"Object",new Object[]{viewName});
242                            } else {
243                                display.show(object);
244                            }
245                            jacRequest.waitForResponse();                                
246                        }                            
247                    } else {
248                        HashMap panels = null;
249                        for (int i = 0; i < 3; i++) {
250                            String panel =
251                                (String) jacRequest.getParameter("panel[" + i + "]");
252                            if (panel != null) {
253                                if (panels == null)
254                                    panels = new HashMap();
255                                panels.put(
256                                    Integer.toString(i),
257                                    new PanelContent("Object", new String[] { panel }));
258                            }
259                        }
260                        if (cgui == null) {
261                            error(
262                                display,
263                                jacRequest,
264                                "No such customized GUI: " + guiID);
265                        } else {
266                            new ShowThread(
267                                display,
268                                sid,
269                                guiID,
270                                cgui,
271                                panels,
272                                jacRequest,
273                                response)
274                                .start();
275                            if (!jacRequest.waitForResponse()) {
276                                showTimeout(response);
277                            }
278                        }
279                    }
280                } else {
281                    handleEvent(jacRequest, response, display, sid, guiID, cgui);
282                }
283            }
284    
285            //ejp.tracer.TracerAPI.disableTracing();
286    
287            logger.info(
288                "request completed " + request.getQueryString()
289                + " -> " + Strings.hex(response));
290            loggerPerf.info("page generated in " + (System.currentTimeMillis() - start) + "ms");
291        }
292    
293        void showTimeout(HttpServletResponse response) throws IOException {
294            Writer output = response.getWriter();
295            output.write("A timeout occurred.");
296        }
297    
298        void handleEvent(
299            JacRequest jacRequest,
300            HttpServletResponse response,
301            WebDisplay display,
302            String sid,
303            String guiID,
304            CustomizedGUI cgui) throws IOException 
305        {
306            String event = (String) jacRequest.getParameter("event");
307            logger.info("handleEvent "+event);
308    
309            DisplayContext context = new DisplayContext(display, null);
310            Collaboration.get().addAttribute(GuiAC.DISPLAY_CONTEXT,context);
311            Collaboration.get().addAttribute(SessionAC.SESSION_ID, sid);
312    
313            // get Integer associated with the event, see in constructor
314            Integer eventID = (Integer) eventList.get(event);
315    
316            if (eventID == null) {
317                error(
318                    display,
319                    jacRequest,
320                    "PROTOCOL ERROR: unknown event " + event);
321                return;
322            }
323    
324            // simple invocation event (with no GUI interaction and
325            // only string parameters supported)
326            if (eventID.intValue() == 1) // onDirectInvoke
327            {
328                String jid = (String) jacRequest.getParameter("jid");
329                String methodName = (String) jacRequest.getParameter("method");
330                String strParam = (String) jacRequest.getParameter("param");
331                if (jid == null) {
332                    error(
333                        display,
334                        jacRequest,
335                        "PROTOCOL ERROR: missing jid argument for event " + event);
336                    return;
337                }
338                if (methodName == null) {
339                    error(
340                        display,
341                        jacRequest,
342                        "PROTOCOL ERROR: missing method argument for event "
343                        + event);
344                    return;
345                }
346                Object object = NameRepository.get().getObject(jid);
347                if (object == null) {
348                    error(
349                        display,
350                        jacRequest,
351                        "PROTOCOL ERROR: jid " + jid + " does not exist");
352                    return;
353                } else {
354                    MethodItem method =
355                        ClassRepository.get().getClass(object).getMethod(methodName);
356                    if (strParam == null) {
357                        EventHandler.get().onInvoke(
358                            context, 
359                            new InvokeEvent(null, object, method));
360                    } else {
361                        EventHandler.get().onInvoke(
362                            context, 
363                            new InvokeEvent(null, object, method, new Object[] { strParam }), 
364                            false, 
365                            null, null);
366                    }
367                    jacRequest.waitForResponse();
368                    return;
369                }
370            }
371    
372            String source = (String) jacRequest.getParameter("source");
373            if (source == null) {
374                error(
375                    display,
376                    jacRequest,
377                    "PROTOCOL ERROR: missing source argument for event " + event);
378                return;
379            }
380            logger.info("  source="+source);
381    
382            if (display.isTimedout(source)) {
383                display.closeWindow(display.getView(source),false);
384                error(display, jacRequest, "ERROR: dialog time out");
385                return;
386            }
387            View dest = display.getView(source);
388            if (dest == null) {
389                error(display, jacRequest, "ERROR: no such view " + source);
390                return;
391            }
392            logger.info("  dest="+dest);
393            logger.info("event = " + event + " -> " + dest + "(" + source + ")");
394    
395            try {
396                String tableEventSource =
397                    (String) jacRequest.getParameter("tableEventSource");
398                if (tableEventSource != null) {
399                    View tableDest = display.getView(tableEventSource);
400                    if (tableDest == null) {
401                        error(
402                            display,
403                            jacRequest,
404                            "ERROR: no such view " + tableEventSource);
405                        return;
406                    }
407                    logger.info("tableEvent = " + tableEventSource + " -> " + tableDest);
408                    String row = (String) jacRequest.getParameter("row");
409                    if (row == null) {
410                        error(
411                            display,
412                            jacRequest,
413                            "PROTOCOL ERROR: missing row argument for tableEvent");
414                        return;
415                    }
416                    String col = (String) jacRequest.getParameter("col");
417                    if (col == null) {
418                        error(
419                            display,
420                            jacRequest,
421                            "PROTOCOL ERROR: missing col argument for tableEvent");
422                        return;
423                    }
424                    if (dest instanceof TableCellViewer) {
425                        dest =
426                            ((TableListener) tableDest).onRowEvent(
427                                new Integer(row).intValue(),
428                                new Integer(col).intValue());
429                    }
430                }
431    
432                new ActionThread(
433                    display,
434                    sid,
435                    guiID,
436                    cgui,
437                    jacRequest,
438                    response,
439                    event,
440                    dest)
441                    .start();
442                if (!jacRequest.waitForResponse()) {
443                    showTimeout(response);
444                }
445    
446            } catch (WrappedThrowableException wrapped) {
447                Throwable e = wrapped.getWrappedThrowable();
448                if (e instanceof EmptyStackException) {
449                    new ShowThread(
450                        display,
451                        sid,
452                        guiID,
453                        cgui,
454                        null,
455                        jacRequest,
456                        response)
457                        .start();
458                    if (!jacRequest.waitForResponse()) {
459                        showTimeout(response);
460                    }
461                } else {
462                    display.showError("Exception", "Caught exception: " + e);
463                    if (!jacRequest.waitForResponse()) {
464                        showTimeout(response);
465                    }
466                    logger.error("handleEvent("+jacRequest+")",e);
467                }
468            } catch (Exception e) {
469                display.showError("Exception", "Caught exception: " + e);
470                if (!jacRequest.waitForResponse()) {
471                    showTimeout(response);
472                }
473                logger.error("handleEvent("+jacRequest+")",e);
474            }
475    
476        }
477    
478        class ShowThread extends Thread {
479            WebDisplay display;
480            String guiID;
481            CustomizedGUI cgui;
482            String sid;
483            JacRequest request;
484            HttpServletResponse response;
485            Map panels;
486    
487            public ShowThread(
488                WebDisplay display,
489                String sid,
490                String guiID,
491                CustomizedGUI cgui,
492                Map panels,
493                JacRequest request,
494                HttpServletResponse response) {
495                this.display = display;
496                this.guiID = guiID;
497                this.cgui = cgui;
498                this.sid = sid;
499                this.request = request;
500                this.response = response;
501                this.panels = panels;
502            }
503    
504            public void run() {
505                loggerThreads.debug("starting ShowThread " + this);
506                try {
507                    Collaboration.get().addAttribute(
508                        GuiAC.DISPLAY_CONTEXT,
509                        new DisplayContext(display, null));
510                    Collaboration.get().addAttribute(SessionAC.SESSION_ID, sid);
511                    WebDisplay.setRequest(request);
512                    WebDisplay.setResponse(response);
513                    try {
514                        display.showCustomized(guiID, cgui, panels);
515                    } catch (Exception e) {
516                        e.printStackTrace();
517                        display.showError("Error", e.getMessage());
518                        if (!request.waitForResponse()) {
519                            showTimeout(response);
520                        }
521                    }
522                } catch (IOException e) {
523                    logger.error("Caught exception in ShowThread",e);
524                } finally {
525                    loggerThreads.debug("ShowThread " + this +" terminated");
526                }
527            }
528        }
529    
530        public class ActionThread extends Thread {
531            WebDisplay display;
532            String guiID;
533            CustomizedGUI cgui;
534            String sid;
535            JacRequest jacRequest;
536            HttpServletResponse response;
537            String event;
538            int eventID;
539            View dest;
540    
541            public ActionThread(
542                WebDisplay display,
543                String sid,
544                String guiID,
545                CustomizedGUI cgui,
546                JacRequest request,
547                HttpServletResponse response,
548                String event,
549                View dest) 
550            {
551                this.display = display;
552                this.guiID = guiID;
553                this.cgui = cgui;
554                this.sid = sid;
555                this.jacRequest = request;
556                this.response = response;
557                this.event = event;
558                this.eventID = ((Integer) eventList.get(event)).intValue();
559                this.dest = dest;
560            }
561    
562            public void run() {
563                loggerThreads.debug("starting ActionThread " + this +" eventID=" + eventID);
564                try {
565                    Collaboration collab = Collaboration.get();
566                    collab.addAttribute(
567                        GuiAC.DISPLAY_CONTEXT,
568                        new DisplayContext(display, null));
569                    collab.addAttribute(SessionAC.SESSION_ID, sid);
570                    WebDisplay.setRequest(jacRequest);
571                    WebDisplay.setResponse(response);
572                    View root = dest.getRootView();
573                    if (root instanceof DialogListener)
574                        ((DialogListener) root).restoreContext();
575                    handleAction();
576                } finally {
577                    cleanup();
578                    loggerThreads.debug("ActionThread " + this +" terminated");
579                }
580            }
581    
582            /**
583             * Cleanup instance variables so that no views are kept i memory
584             */
585            public void cleanup() {
586                dest = null;
587                display = null;
588                jacRequest = null;
589                response = null;
590                guiID = null;
591                cgui = null;
592                sid = null;
593                event = null;
594            }
595    
596            public void handleAction() {
597    
598                try {
599                    switch (eventID) {
600                        case 2 :
601                            { // onView
602                                String index =
603                                    (String) jacRequest.getParameter("index");
604                                if (index == null) {
605                                    index =
606                                        (String)jacRequest.getParameter(
607                                            "index_" + display.getViewID(dest));
608                                    if (index == null) {
609                                        error(display,jacRequest,
610                                              "PROTOCOL ERROR: missing index argument for event "+event);
611                                    }
612                                }
613                                if (index != null) {
614                                    ((CollectionListener)dest).onView(
615                                        Integer.parseInt(index));
616                                }
617                            }
618                            break;
619                        case 33 :
620                            { // onViewObject
621                                String name =
622                                    (String)jacRequest.getParameter("object");
623                                if (name == null) {
624                                    error(display, jacRequest,
625                                          "PROTOCOL ERROR: missing object argument for event "+event);
626                                } else {
627                                    logger.info(dest+".onViewObject("+name+")");
628                                    ((CollectionListener)dest).onViewObject(name);
629                                }
630                            }
631                            break;
632                        case 27 :
633                            { // onRemove
634                                String index =
635                                    (String)jacRequest.getParameter("index");
636                                if (index == null) {
637                                    error(display, jacRequest,
638                                          "PROTOCOL ERROR: missing index argument for event "+event);
639                                } else {
640                                    ((CollectionListener) dest).onRemove(
641                                        Integer.parseInt(index));
642                                }
643                            }
644                            break;
645                        case 3 :
646                            { // onTableInvoke
647                                String index =
648                                    (String) jacRequest.getParameter("index");
649                                String method =
650                                    (String) jacRequest.getParameter("method");
651                                if (index == null) {
652                                    error(display,jacRequest,
653                                          "PROTOCOL ERROR: missing index argument for event "+event);
654                                } else if (method == null) {
655                                    error(display,jacRequest,
656                                          "PROTOCOL ERROR: missing method argument for event "+event);
657                                } else {
658                                    ((CollectionListener) dest).onTableInvoke(
659                                        Integer.parseInt(index),
660                                        method);
661                                }
662                            }
663                            break;
664                        case 4 :
665                            { // onSelect
666                                String index =
667                                    (String) jacRequest.getParameter("index");
668                                if (index == null) {
669                                    error(display,jacRequest,
670                                          "PROTOCOL ERROR: missing index argument for event "+event);
671                                } else {
672                                    logger.info("TabsListener.onSelect(" + index + ")");
673                                    ((TabsListener) dest).onSelect(
674                                        Integer.parseInt(index));
675                                }
676                            }
677                            break;
678                        case 5 : // onInvoke
679                            loggerEvents.debug(dest+".onInvoke");
680                            ((MethodListener) dest).onInvoke();
681                            break;
682                        case 6 : // onSelection
683                            ((SelectionListener) dest).onSelection();
684                            break;
685                        case 7 : // onCellSelection
686                            String row = (String) jacRequest.getParameter("row");
687                            if (row == null) {
688                                error(display, jacRequest,
689                                      "PROTOCOL ERROR: missing row argument for event "+event);
690                            } else {
691                                String col =
692                                    (String) jacRequest.getParameter("col");
693                                if (row == null) {
694                                    error(display,jacRequest,
695                                          "PROTOCOL ERROR: missing row argument for event "+event);
696                                } else {
697                                    ((TableListener) dest).onCellSelection(
698                                        Integer.parseInt(row),
699                                        Integer.parseInt(col));
700                                }
701                            }
702    
703                            break;
704                        case 8 : // onHeaderClick
705                            String col = (String) jacRequest.getParameter("col");
706                            if (col == null) {
707                                error(display,jacRequest,
708                                      "PROTOCOL ERROR: missing col argument for event "+event);
709                            } else {
710                                ((TableListener) dest).onHeaderClick(
711                                    Integer.parseInt(col));
712                            }
713                            break;
714                        case 9 : // onClose
715                            if ((String)jacRequest.getParameter("onOK") != null) {
716                                loggerEvents.debug(dest+".onOK");
717                                ((WindowListener)dest).onOK(jacRequest);
718                            } else if ((String)jacRequest.getParameter("onCancel") != null) {
719                                loggerEvents.debug(dest+".onCancel");
720                                ((WindowListener)dest).onCancel();
721                            } else {
722                                loggerEvents.debug(dest+".onOK");
723                                ((WindowListener)dest).onOK(jacRequest);
724                            }
725                            break;
726                        case 10 : // onValidate
727                            if ((String) jacRequest.getParameter("onOK") != null) {
728                                loggerEvents.debug(dest+".onOK");
729                                ((DialogListener) dest).onOK(jacRequest);
730                            } else if ((String)jacRequest.getParameter("onCancel") != null) {
731                                loggerEvents.debug(dest+".onCancel");
732                                ((DialogListener) dest).onCancel();
733                            }
734                            break;
735                        case 11 : // onOK
736                            ((WindowListener) dest).onOK(jacRequest);
737                            break;
738                        case 12 : // onCancel
739                            ((WindowListener) dest).onCancel();
740                            break;
741                        case 34 : // onRefresh
742                            loggerEvents.debug(dest+".onRefresh");
743                            ((WindowListener)dest).onRefresh(jacRequest);
744                            break;
745                        case 13 : // onAddToCollection
746                            ((CollectionListener)dest).onAddToCollection();
747                            break;
748                        case 31 : // onAddExistingToCollection
749                            ((CollectionListener)dest).onAddExistingToCollection();
750                            break;
751                        case 14 : // onRemoveFromCollection
752                            ((CollectionListener)dest).onRemoveFromCollection();
753                            break;
754                        case 15 : // onNext
755                            ((CollectionListener)dest).onNext();
756                            break;
757                        case 29 : // onLast
758                            ((CollectionListener)dest).onLast();
759                            break;
760                        case 16 : // onPrevious
761                            ((CollectionListener)dest).onPrevious();
762                            break;
763                        case 28 : // onFirst
764                            ((CollectionListener)dest).onFirst();
765                            break;
766                        case 35: // onRefreshCollection
767                            ((CollectionListener)dest).onRefreshCollection();
768                            break;  
769                        case 17 : // onSelectNode
770                            loggerEvents.debug(dest+".onSelectNode");
771                            ((TreeListener) dest).onSelectNode(
772                                (String) jacRequest.getParameter("nodePath"));
773                            break;
774                        case 18 : // onExpandNode
775                            loggerEvents.debug(dest+".onExpandNode");
776                            ((TreeListener) dest).onExpandNode(
777                                (String) jacRequest.getParameter("nodePath"));
778                            break;
779                        case 19 : // onCollapseNode
780                            loggerEvents.debug(dest+".onCollapseNode");
781                            ((TreeListener) dest).onCollapseNode(
782                                (String) jacRequest.getParameter("nodePath"));
783                            break;
784                        case 20 : // onMenuClick
785                            loggerEvents.debug(dest+".onMenuClick");
786                            ((MenuListener) dest).onMenuClick(
787                                (String) jacRequest.getParameter("item"));
788                            break;
789                        case 21 : // onCreateObject
790                            ((ChoiceListener) dest).onCreateObject();
791                            break;
792                        case 22 : // onLoadAttachment
793                            ((AttachmentListener) dest).onLoadAttachment();
794                            break;
795                        case 23 : // onPreviousInCollection
796                            ((CollectionItemViewListener) dest)
797                                .onPreviousInCollection();
798                            break;
799                        case 24 : // onNextInCollection
800                            ((CollectionItemViewListener) dest)
801                                .onNextInCollection();
802                            break;
803                        case 25 : // onBackToCollection
804                            ((CollectionItemViewListener) dest)
805                                .onBackToCollection();
806                            break;
807                        case 26 : // onRemoveInCollection
808                            ((CollectionItemViewListener) dest)
809                                .onRemoveInCollection();
810                            break;
811                        case 30 : // onAddEmbedded
812                            ((TableListener) dest).onEmbeddedAddToCollection();
813                            break;
814                        case 32 : // onSetDefaults
815                            ((TableListener) dest).onSetDefaults();
816                            break;
817                        default :
818                            throw new Exception(
819                                "Unknown event " + event + "(" + eventID + ")");
820                    }
821    
822                } catch (Exception e) {
823                    logger.error("handleAction(eventID="+eventID+",event="+event+
824                                 ",sid="+sid+") failed",e);
825                    display.show(e);
826                                    //            display.showError("Error",e.getMessage());
827                }
828            }
829    
830        }
831    
832        protected void error(
833            WebDisplay display,
834            JacRequest jacRequest,
835            String message) 
836        {
837            logger.error("message",new Exception());
838            display.showError("Servlet error", message);
839            jacRequest.waitForResponse();
840        }
841    
842    }