1    package com.instantbank.lettertemplate.editor.web;
2    
3    import java.io.IOException;
4    import java.io.ObjectInputStream;
5    import java.io.ObjectOutputStream;
6    import java.io.StringWriter;
7    import java.io.PrintWriter;
8    import java.io.FileNotFoundException;
9    import java.util.Hashtable;
10   import java.util.ArrayList;
11   import java.util.Set;
12   import java.util.Iterator;
13   
14   import javax.servlet.ServletException;
15   import javax.servlet.RequestDispatcher;
16   
17   import javax.servlet.http.HttpServlet;
18   import javax.servlet.http.HttpServletRequest;
19   import javax.servlet.http.HttpServletResponse;
20   import javax.servlet.http.HttpSession;
21   
22   import java.rmi.RemoteException;
23   import javax.naming.InitialContext;
24   import com.instantbank.lettertemplate.control.util.JSPUtil;
25   import com.instantbank.lettertemplate.control.util.WebKeys;
26   import com.instantbank.lettertemplate.editor.util.LetterOp;
27   import com.instantbank.component.lettertemplate.util.LetterComponent;
28   import com.instantbank.component.lettertemplate.util.Template;
29   import com.instantbank.component.lettertemplate.util.LetterViewable;
30   import com.instantbank.common.utilcomponents.CodeDescription;
31   import com.instantbank.common.utilcomponents.Debug;
32   import com.instantbank.common.utilcomponents.CommonUtil;
33   import com.instantbank.common.utilcomponents.LetterTemplateExceptionMessage;
34   import com.instantbank.common.utilcomponents.LetterTemplateGlobals;
35   import com.instantbank.common.utilcomponents.JNDINames;
36   import com.instantbank.component.lettertemplate.ejb.LetterTemplate;
37   import com.instantbank.common.utilcomponents.DAOException;
38   import com.instantbank.component.lettertemplate.ejb.LetterTemplateHome;
39   import com.instantbank.component.job.util.Field;
40   import com.instantbank.lettertemplate.control.LetterTemplateEventException;
41   
42   /**
43    *  Servlet acting as a controller in order to ask ejb services for letter's
44    *  template editor. Each method in this servlet has a corresponding one
45    *  --having the same name, but different parameters-- in the {@link
46    *  com.instantbank.lettertemplate.editor.applet.TemplateEditorProxy} class and
47    *  in the {@link com.instantbank.component.lettertemplate.ejb.LetterTemplate}
48    *  interface. Actual parameters in the TemplateEditorProxy methods are sent to
49    *  this servlet --in the request-- and must be explicitly extracted by the
50    *  corresponding methods in the servlet in order to be used as parameters for
51    *  the services specified in the LetterTemplate interface.
52    *
53    * @author InstantBank (Rodrigo Lopez, Consuelo Franky)
54    * @created September 2002
55    */
56   public class TemplateEditorServlet extends HttpServlet {
57   
58     /**
59      *  The home for the ejb that provides the services requested by this
60      *  servlet.
61      */
62     private LetterTemplateHome lethome = null;
63   
64     /**
65      *  The ejb that provides the services for this servlet.
66      */
67     private LetterTemplate letejb = null;
68   
69     /**
70      * A hash table with company fields information
71      */
72     private Hashtable hashFields = null;
73   
74     /**
75      * The ubiquitous debug object.
76      */
77     private Debug debug = null;
78   
79   
80     /**
81      *  Description of the Method
82      *
83      * @exception ServletException
84      */
85     public void init() throws ServletException {
86       debug = new Debug();
87       debug.setDebugginOn(true);
88       debug.setPreMessage("** TemplateEditorServlet: ");
89   
90       debug.println("init()");
91   
92       //obtain LetterTemplateHome reference
93       try {
94         // Contact the LetterTemplateHome through JNDI.
95         InitialContext ctx = new InitialContext();
96         lethome = (LetterTemplateHome)ctx.lookup
97           (JNDINames.LETTERTEMPLATE_EJBHOME);
98       }
99       catch(Exception e) {
100        e.printStackTrace();
101        debug.println("Problem instantiating LetterTemplate EJB:" + e.toString());
102        throw new ServletException(LetterTemplateExceptionMessage.PROBLEM_INSTANTIATING_LETTERS_EJB);
103      }
104  
105    }
106  
107  
108    /**
109     *  Acts as a dispatcher for the services encoded as {@link
110     *  com.instantbank.lettertemplate.editor.util.LetterOp LetterOp} constants.
111     *
112     * @param req
113     * @param resp
114     * @exception ServletException
115     * @exception IOException
116     */
117    public void doPost(HttpServletRequest req, HttpServletResponse resp)
118       throws ServletException, IOException {
119  
120      ObjectInputStream in = new ObjectInputStream(req.getInputStream());
121      ObjectOutputStream out = new ObjectOutputStream(resp.getOutputStream());
122  
123      try {
124  
125        // gets LetterTemplate ejb instance reference:
126        letejb = (LetterTemplate)req.getSession()
127          .getAttribute(WebKeys.LetterTemplateEJB);
128  
129        String companyId = companyId = (String)req.getSession()
130          .getAttribute(WebKeys.CompanyId);
131        Long userId = (Long)req.getSession()
132          .getAttribute(WebKeys.UserId);
133  
134        if(letejb == null) {
135          debug.println("creating reference to LetterTemplate EJB");
136          letejb = lethome.create(companyId, userId);
137          req.getSession().setAttribute
138            (WebKeys.LetterTemplateEJB, letejb);
139        }
140  
141        String temporalDir
142           = (String)req.getSession().getAttribute(WebKeys.ImagesTemporalPath);
143        String rtf2foConfDir
144           = (String)req.getSession().getAttribute(WebKeys.RtfToFoConfigPath);
145  
146        debug.println("rtf2foConfDir = " + rtf2foConfDir);
147  
148        debug.println("ejb contacted");
149  
150        int opCode = ((Integer)in.readObject()).intValue();
151  
152        switch (opCode) {
153  
154          // get letter categories. Can use the servlet context.
155          case LetterOp.LOADCATEGORIES:
156            loadCategories(companyId, out);
157            break;
158          //Loads code and time stamps of a template and components
159          //not necessarily related to the template.
160          case LetterOp.LOADCODESTAMP:
161            loadCodesStamps(in, out);
162            break;
163          //Load a full Template starting from its code.
164          case LetterOp.LOADTEMPL:
165            loadTemplate(req, in, out);
166            break;
167          //Load templates <code,names> for a given category and print type.
168          case LetterOp.LOADTEMPLNAMES:
169            loadTemplatesDescription(in, out);
170            break;
171          //Loads code and stamp of a template and its bound components.
172          case LetterOp.LOADTEMPLCODES:
173            loadTemplateCodes(in, out);
174            break;
175          //Stores a full template and returns <code,stamps> of the
176          // template and its components.
177          case LetterOp.STORETEMPLATE:
178            storeTemplate(companyId, in, out);
179            break;
180          //Loads a component after its code.
181          case LetterOp.LOADCOMPONENT:
182            loadComponent(req, in, out);
183            break;
184          //Load components description for a given type and print type.
185          case LetterOp.LOADCOMPDESCR:
186            loadComponentsDescription(in, out);
187            break;
188          //get [code, stamp] for specified component
189          case LetterOp.LOADCOMPCODE:
190            loadComponentCode(in, out);
191            break;
192          //Stores a component.
193          case LetterOp.STORECOMPONENT:
194            storeComponent(companyId, in, out);
195            break;
196          //Stores a component and bound it to a template.
197          case LetterOp.STORECOMPONENTAS:
198            storeComponentAs(companyId, in, out);
199            break;
200          //Loads an image from the images repository
201          case LetterOp.LOADIMG:
202            loadImageRepository(in, out);
203            break;
204          //Load images names
205          case LetterOp.LOADIMGNAMES:
206            loadImagesNamesRepository(companyId, in, out);
207            break;
208          //loads variables
209          case LetterOp.LOADVARIABLES:
210            loadVariables(out);
211            break;
212          //loads variable formtas
213          case LetterOp.LOADVARIABLEFORMATS:
214            loadVariableFormats(out);
215            break;
216          //Control timeout
217          case LetterOp.CONTROLTIMEOUT:
218            controlTimeout(out, req, resp);
219            break;
220          //forward to another url
221          case LetterOp.EXIT:
222            String url = (String)in.readObject();
223            //The target url
224            exit(req, resp, url);
225            break;
226          default:
227            debug.println("default: I don't know what happened.");
228            out.writeObject(null);
229            break;
230        }
231      }
232      catch(Exception ex) {
233        debug.println(CommonUtil.stackTraceToString(ex));
234      }
235      finally {
236        in.close();
237        out.close();
238      }
239    }
240  
241  
242    /**
243     *  Loads all [code, description] of the categories in the current company,
244     *  from the web context or from the database.
245     *
246     * @param companyId
247     * @param out
248     * @exception ServletException
249     * @exception IOException
250     */
251    private void loadCategories(String companyId, ObjectOutputStream out)
252       throws ServletException, IOException {
253      try {
254        debug.println("Starting loadCategories");
255        Hashtable categoryTable = CommonUtil.getWebContextVariable
256          (getServletContext(), WebKeys.CategoryTable);
257  
258        debug.println("Category table loaded");
259        Object list = categoryTable.get(companyId);
260        debug.println("Category list axtracted");
261  
262        CodeDescription[] categ = null;
263        if(list != null) {
264          debug.println("takes categories from web context variable");
265          categ = (CodeDescription[])list;
266        }
267        else {
268          debug.println("takes categories from the database");
269          categ = letejb.loadCategories();
270          // puts categories in web context variable:
271          categoryTable.put(companyId, categ);
272          getServletContext().setAttribute
273            (WebKeys.CategoryTable, categoryTable);
274        }
275  
276        if(categ != null) {
277          debug.println("categories are not null");
278          out.writeObject(categ);
279        }
280        else {
281          debug.println("categories are null");
282          out.writeObject(null);
283        }
284      }
285      catch(RemoteException rex) {
286        debug.println("RemoteException in LOADCATEGORIES: " + rex.getMessage());
287        out.writeObject(null);
288      }
289      catch(DAOException lex) {
290        debug.println("In LOADCATEGORIES: " + lex.getMessage());
291        out.writeObject(null);
292      }
293    }
294  
295  
296    /**
297     *  Loads code and stamp of template and components. It sends back --to the
298     *  proxy-- a CodeDescription array where:
299     *  <ul>
300     *    <li> CodeDescription [0] is [code, stamp] of template, if it exists.
301     *    or it is [LetterTemplateGlobals.UNDEF,LetterTemplateGlobals.STR_UNDEF] if template doesn't
302     *    exist.
303     *    <li> CodeDescription [i] is [code, stamp] of component, if it exists,
304     *    or it is [LetterTemplateGlobals.UNDEF,LetterTemplateGlobals.STR_UNDEF] if component doesn't
305     *    exist --for i = 1(HEADER),2(BODY),3(CLOSING)--
306     *
307     * @param in
308     * @param out
309     * @exception ServletException
310     * @exception IOException
311     */
312    private void loadCodesStamps(ObjectInputStream in, ObjectOutputStream out)
313       throws ServletException, IOException {
314      try {
315        long categ = ((Long)in.readObject()).longValue();
316        int pType = ((Integer)in.readObject()).intValue();
317        String templ = (String)in.readObject();
318        String header = (String)in.readObject();
319        String body = (String)in.readObject();
320        String closing = (String)in.readObject();
321  
322        debug.println("invokes loadCodesStamps");
323        CodeDescription[] codeStamps =
324          letejb.loadCodesStamps(categ, pType, templ, header, body, closing);
325  
326        out.writeObject(codeStamps);
327  
328      }
329      catch(RemoteException rex) {
330        debug.println("RemoteException in LOADCODESTAMP: " + rex.getMessage());
331        out.writeObject(null);
332      }
333      catch(DAOException dex) {
334        debug.println("DAOException with LOADCODESTAMP: "
335          + dex.getMessage());
336        out.writeObject(null);
337      }
338      catch(ClassNotFoundException cfx) {
339        debug.println("Probably a casting problem with LOADCODESTAMP: "
340          + cfx.getMessage());
341        out.writeObject(null);
342      }
343    }
344  
345  
346    /**
347     *  Loads a letters template of the current company, corresponding to a
348     *  code. The object send back to the proxy is
349     *    a pair containing the full template structure extracted
350     *            from the data base and a message containing the names of
351     *            the variables with inconsistent date offsets. Those offsets
352     *            are forced to zero.
353     *
354     * @param req The standard request object
355     * @param in Communication channel from the servlet proxy
356     * @param out Communication channel to the servlet proxy
357     * @exception ServletException
358     * @exception IOException
359     */
360    private void loadTemplate(HttpServletRequest req, ObjectInputStream in, ObjectOutputStream out)
361       throws ServletException, IOException {
362      try {
363        long code = ((Long)in.readObject()).longValue();
364        debug.println("invokes loadTemplate");
365        Template templ = letejb.loadTemplate(code);
366        String msg = null;
367        ArrayList resp = null;
368  
369        if(templ != null) {  //tries to fix inconsistent date offsets
370          debug.println("Template is not null.");
371          resp = new ArrayList(2);
372          Set brokenVars = fixDateOffset(req, templ);
373          msg = brokenVarNames(brokenVars);
374          resp.add(templ);
375          resp.add(msg);
376  
377          out.writeObject(resp);
378        }
379        else {
380          debug.println("Template is null");
381          out.writeObject(null);
382        }
383      }
384      catch(RemoteException rex) {
385        debug.println("RemoteException in LOADTEMPL: " + rex.getMessage());
386        out.writeObject(null);
387      }
388      catch(DAOException dex) {
389        debug.println("DAOException with LOADTEMPL: "
390          + dex.getMessage());
391        out.writeObject(null);
392      }
393      catch(ClassNotFoundException cfx) {
394        debug.println("Probably a casting problem with LOADTEMPL: "
395          + cfx.getMessage());
396        out.writeObject(null);
397      }
398      catch(Exception ex) {
399        debug.println(
400          "Probably the information about company fields was not loaded: "
401          + ex.getMessage());
402        out.writeObject(null);
403      }
404    }
405  
406  
407    /**
408     *  Asks for code and description of the templates, for a given category and
409     *  print type. Sends back --to the proxy-- an array of < code,name>
410     *  pairs of templates sorted by name.
411     *
412     * @param in
413     * @param out
414     * @exception ServletException
415     * @exception IOException
416     */
417    private void loadTemplatesDescription(
418                                          ObjectInputStream in, ObjectOutputStream out)
419       throws ServletException, IOException {
420      try {
421        long category = ((Long)in.readObject()).longValue();
422        int pType = ((Integer)in.readObject()).intValue();
423  
424        debug.println("invokes loadTemplatesDescription");
425        CodeDescription[] tnresp
426           = letejb.loadTemplatesDescription(category, pType);
427        if(tnresp != null) {
428          debug.println("set of template names is not null.");
429          out.writeObject(tnresp);
430        }
431        else {
432          debug.println("set of template names is null");
433          out.writeObject(null);
434        }
435      }
436      catch(RemoteException rex) {
437        debug.println("RemoteException in LOADTEMPLNAMES: " + rex.getMessage());
438        out.writeObject(null);
439      }
440      catch(DAOException dex) {
441        debug.println("DAOException with LOADTEMPLNAMES: "
442          + dex.getMessage());
443        out.writeObject(null);
444      }
445      catch(ClassNotFoundException cfx) {
446        debug.println("Probably a casting problem with LOADTEMPLNAMES: "
447          + cfx.getMessage());
448        out.writeObject(null);
449      }
450    }
451  
452  
453    /**
454     *  Asks for the service of loading < code, stamp> for a template and its
455     *  components, after its code. Sends back --to the proxy-- a < code,
456     *  stamp> array of the template in the <a
457     *  href="../applet/package-summary.html#thbc">THBC order.</a>
458     *
459     * @param in
460     * @param out
461     * @exception ServletException
462     * @exception IOException
463     */
464    private void loadTemplateCodes(ObjectInputStream in, ObjectOutputStream out)
465       throws ServletException, IOException {
466      try {
467        long code = ((Long)in.readObject()).longValue();
468  
469        debug.println("invokes loadTemplateCodes");
470        CodeDescription[] codeDescr =
471          letejb.loadTemplateCodes(code);
472  
473        out.writeObject(codeDescr);
474  
475      }
476      catch(RemoteException rex) {
477        debug.println("RemoteException in LOADTEMPLCODES: " + rex.getMessage());
478        out.writeObject(null);
479      }
480      catch(DAOException dex) {
481        debug.println("DAOException with LOADTEMPLCODES: "
482          + dex.getMessage());
483        out.writeObject(null);
484      }
485      catch(ClassNotFoundException cfx) {
486        debug.println("Probably a casting problem with LOADTEMPLCODES: "
487          + cfx.getMessage());
488        out.writeObject(null);
489      }
490    }
491  
492  
493    /**
494     *  Asks for the service of storing a template. Sends back --to the proxy--
495     *  an array of < code, stamp> of the stored elements in the <a
496     *  href="../applet/package-summary.html#thbc">THBC order.</a>
497     *
498     * @param companyId
499     * @param in
500     * @param out
501     * @exception ServletException
502     * @exception IOException
503     */
504    private void storeTemplate(String companyId, ObjectInputStream in, ObjectOutputStream out)
505       throws ServletException, IOException {
506      try {
507        Template templ = (Template)in.readObject();
508        debug.println("invokes storeTemplate");
509        CodeDescription[] codesStamps = letejb.storeTemplate(templ);
510        // invalidates context variable corresponding to templates list:
511        CommonUtil.putVariableInContext(getServletContext(), companyId,
512          WebKeys.TemplatesTable, "");
513        // invalidates context variable corresponding to unlinked component list:
514        CommonUtil.putVariableInContext(getServletContext(), companyId,
515          WebKeys.ComponentsTable, "");
516        out.writeObject(codesStamps);
517      }
518      catch(DAOException lex) {
519        debug.println("Problems storing template with STORETEMPLATE");
520        debug.println(CommonUtil.stackTraceToString(lex));
521        out.writeObject(null);
522      }
523      catch(ClassNotFoundException cfx) {
524        debug.println("Probably a casting problem with STORETEMPLATE: "
525          + cfx.getMessage());
526        debug.println(CommonUtil.stackTraceToString(cfx));
527        out.writeObject(null);
528      }
529    }
530  
531  
532    /**
533     *  Loads a letters component of the current company, corresponding to a
534     *  code. The object send back to the proxy is
535     *    a pair containing the full component structure extracted
536     *            from the data base and a message containing the names of
537     *            the variables with inconsistent date offsets. Those offsets
538     *            are forced to zero.
539     *
540     * @param req The standard request object
541     * @param in Communication channel from the servlet proxy.
542     * @param out Communication channel to the servlet proxy.
543     * @exception ServletException
544     * @exception IOException
545     */
546    private void loadComponent(HttpServletRequest req, ObjectInputStream in,
547                               ObjectOutputStream out)
548       throws ServletException, IOException {
549      try {
550        long code = ((Long)in.readObject()).longValue();
551        debug.println("invokes loadComponent(code)");
552        LetterComponent comp = letejb.loadComponent(code);
553        String msg = null;
554        ArrayList resp = null;
555        if(comp != null) {
556          debug.println("component was loaded");
557          resp = new ArrayList(2);
558          Set brokenVars = fixDateOffset(req, comp);
559          msg = brokenVarNames(brokenVars);
560          resp.add(comp);
561          resp.add(msg);
562        }
563        out.writeObject(resp);
564  
565      }
566      catch(RemoteException rex) {
567        debug.println("RemoteException in LOADCOMPONENT: " + rex.getMessage());
568        out.writeObject(null);
569      }
570      catch(DAOException dex) {
571        debug.println("DAOException with LOADCOMPONENT: "
572          + dex.getMessage());
573        out.writeObject(null);
574      }
575      catch(ClassNotFoundException cfx) {
576        debug.println("Probably a casting problem with LOADCOMPONENT: "
577          + cfx.getMessage());
578        out.writeObject(null);
579      }
580      catch(Exception ex) {
581        debug.println(
582          "Probably the information about company fields was not loaded: "
583          + ex.getMessage());
584        out.writeObject(null);
585      }
586    }
587  
588  
589    /**
590     *  Asks for code and description of the components, for a given component
591     *  type and print type. Sens back --to the proxy-- An array of <
592     *  code,name> pairs of components, sorted by name. If there are no
593     *  components, "null" is sent back.
594     *
595     * @param in
596     * @param out
597     * @exception ServletException
598     * @exception IOException
599     */
600    private void loadComponentsDescription(
601                                           ObjectInputStream in, ObjectOutputStream out)
602       throws ServletException, IOException {
603      try {
604        int compType = ((Integer)in.readObject()).intValue();
605        int pType = ((Integer)in.readObject()).intValue();
606  
607        debug.println("invokes loadComponentsDescription");
608        CodeDescription[] cmpResp = letejb.loadComponentsDescription(compType, pType);
609        if(cmpResp != null && cmpResp.length != 0) {
610          debug.println("set of components names is not null.");
611          out.writeObject(cmpResp);
612        }
613        else {
614          debug.println("set of components names is null");
615          out.writeObject(null);
616        }
617      }
618      catch(RemoteException rex) {
619        debug.println("RemoteException in LOADCOMPDESCR: " + rex.getMessage());
620        out.writeObject(null);
621      }
622      catch(DAOException dex) {
623        debug.println("DAOException with LOADCOMPDESCR: "
624          + dex.getMessage());
625        out.writeObject(null);
626      }
627      catch(ClassNotFoundException cfx) {
628        debug.println("Probably a casting problem with LOADCOMPDESCR: "
629          + cfx.getMessage());
630        out.writeObject(null);
631      }
632    }
633  
634  
635    /**
636     *  Loads the < code,stamp> of a component from the database. Sends back
637     *  --to the proxy-- The < code, stamp> of the component. If the
638     *  component doesn't exists the returned value is <tt> <
639     *  LetterTemplateGlobals.UNDEF, LetterTemplateGlobals.STR_UNDEF></tt> .
640     *
641     * @param in
642     * @param out
643     * @exception ServletException
644     * @exception IOException
645     */
646    private void loadComponentCode(ObjectInputStream in, ObjectOutputStream out)
647       throws ServletException, IOException {
648      try {
649        debug.println("invokes letejb.loadComponentCode");
650        int type = ((Integer)in.readObject()).intValue();
651        int pType = ((Integer)in.readObject()).intValue();
652        String name = (String)in.readObject();
653  
654        CodeDescription codeStamp = letejb.loadComponentCode(type, pType, name);
655        out.writeObject(codeStamp);
656      }
657      catch(RemoteException rex) {
658        debug.println("RemoteException in LOADCOMPCODE: " + rex.getMessage());
659        out.writeObject(new Long(LetterTemplateGlobals.TROUBLE_SIGNAL));
660      }
661      catch(DAOException dex) {
662        debug.println("DAOException with LOADCOMPCODE: "
663          + dex.getMessage());
664        out.writeObject(null);
665      }
666      catch(ClassNotFoundException cfx) {
667        debug.println("Probably a casting problem with LOADCOMPCODE: "
668          + cfx.getMessage());
669        out.writeObject(null);
670      }
671    }
672  
673  
674    /**
675     *  Asks for the service of storing a letter component without changing its
676     *  links with any template. An old version of the component must exist
677     *  before asking the service. Sends back --to the proxy-- the < code,
678     *  stamp> of the saved component.
679     *
680     * @param companyId
681     * @param in
682     * @param out
683     * @exception ServletException
684     * @exception IOException
685     */
686    private void storeComponent(String companyId, ObjectInputStream in, ObjectOutputStream out)
687       throws ServletException, IOException {
688      try {
689        LetterComponent component = (LetterComponent)in.readObject();
690        debug.println("invokes storeComponent(component)");
691        CodeDescription codes = letejb.storeComponent(component);
692        // invalidates context variable corresponding to unlinked component list:
693        CommonUtil.putVariableInContext(getServletContext(), companyId,
694          WebKeys.ComponentsTable, "");
695  
696        out.writeObject(codes);
697      }
698      catch(RemoteException rex) {
699        debug.println("RemoteException in STORECOMPONENT: " + rex.getMessage());
700        out.writeObject(null);
701      }
702      catch(DAOException dex) {
703        debug.println("DAOException with STORECOMPONENT: "
704          + dex.getMessage());
705        out.writeObject(null);
706      }
707      catch(ClassNotFoundException cfx) {
708        debug.println("Probably a casting problem with STORECOMPONENT: "
709          + cfx.getMessage());
710        out.writeObject(null);
711      }
712    }
713  
714  
715    /**
716     *  Asks for the service of storing a letter component bound to a template.
717     *  Following its type (header, body, closing) it also replaces the
718     *  corresponding component of the template. Sends back --to the sender--
719     *  the < code,stamp> of the saved component.
720     *
721     * @param companyId
722     * @param in
723     * @param out
724     * @exception ServletException
725     * @exception IOException
726     */
727    private void storeComponentAs(String companyId, ObjectInputStream in, ObjectOutputStream out)
728       throws ServletException, IOException {
729      try {
730        long templCode = ((Long)in.readObject()).longValue();
731        LetterComponent component = (LetterComponent)in.readObject();
732        debug.println("invokes storeComponent(component)");
733        CodeDescription codes = letejb.storeComponentAs(templCode, component);
734        // invalidates context variable corresponding to unlinked component list:
735        CommonUtil.putVariableInContext(getServletContext(), companyId,
736          WebKeys.ComponentsTable, "");
737        out.writeObject(codes);
738      }
739      catch(RemoteException rex) {
740        debug.println("RemoteException in STORECOMPONENTAS: " + rex.getMessage());
741        out.writeObject(null);
742      }
743      catch(DAOException dex) {
744        debug.println("DAOException with STORECOMPONENTAS: "
745          + dex.getMessage());
746        out.writeObject(null);
747      }
748      catch(ClassNotFoundException cfx) {
749        debug.println("Probably a casting problem with STORECOMPONENTAS: "
750          + cfx.getMessage());
751        out.writeObject(null);
752      }
753    }
754  
755  
756    /**
757     *  Asks the service of loading an image --of the current company-- after
758     *  its name. Sends back --to the proxy-- an array containing the raw bytes
759     *  of the image. See {@link com.instantbank.component.lettertemplate.ejb.LetterTemplate#loadImageRepository(String)}
760     *
761     * @param in
762     * @param out
763     * @exception ServletException
764     * @exception IOException
765     */
766    private void loadImageRepository(ObjectInputStream in, ObjectOutputStream out)
767       throws ServletException, IOException {
768      try {
769        String name = (String)in.readObject();
770  
771        debug.println("invokes letejb.loadImageRepository()");
772        byte[] imageFromDB = letejb.loadImageRepository(name);
773        if(imageFromDB != null) {
774          debug.println("imageFromDB is not null");
775          out.writeObject(imageFromDB);
776        }
777        else {
778          debug.println("imageFromDB is null");
779          out.writeObject(null);
780        }
781      }
782      catch(RemoteException rex) {
783        debug.println("RemoteException in LOADIMG: " + rex.getMessage());
784        out.writeObject(null);
785      }
786      catch(DAOException lex) {
787        debug.println("In LOADIMG: " + lex.getMessage());
788        out.writeObject(null);
789      }
790      catch(ClassNotFoundException cfx) {
791        debug.println("Probably a casting problem with LOADIMG: "
792          + cfx.getMessage());
793        out.writeObject(null);
794      }
795    }
796  
797  
798    /**
799     *  Loads the names of the images from the web context or from the data
800     *  base. Sends back --to the proxy-- an array of images names. If there are
801     *  no images, "null" is sent back.
802     *
803     * @param companyId
804     * @param in
805     * @param out
806     * @exception ServletException
807     * @exception IOException
808     */
809    private void loadImagesNamesRepository(String companyId,
810                                           ObjectInputStream in, ObjectOutputStream out)
811       throws ServletException, IOException {
812  
813      try {
814        debug.println("Starting loadImagesNamesRepository");
815        Hashtable imagesNamesTable = CommonUtil.getWebContextVariable
816          (getServletContext(), WebKeys.ImageTable);
817  
818        debug.println("Images names table loaded");
819        Object list = imagesNamesTable.get(companyId);
820        debug.println("Images names list extracted");
821  
822        CodeDescription[] imgresp = null;
823        if(list != null) {
824          debug.println("takes images names from web context variable");
825          imgresp = (CodeDescription[])list;
826        }
827        else {
828          debug.println("takes images name from database");
829          imgresp = letejb.loadImagesNamesRepository();
830          // puts images names in web context variable:
831          imagesNamesTable.put(companyId, imgresp);
832          getServletContext().setAttribute
833            (WebKeys.ImageTable, imagesNamesTable);
834        }
835  
836        if(imgresp != null && imgresp.length != 0) {
837          debug.println("set of images is not null.");
838          out.writeObject(CodeDescription.toDescriptions(imgresp));
839        }
840        else {
841          debug.println("set of images is null");
842          out.writeObject(null);
843        }
844      }
845      catch(RemoteException rex) {
846        debug.println("RemoteException with LOADIMGNAMES: " + rex.getMessage());
847        out.writeObject(null);
848      }
849      catch(DAOException dex) {
850        debug.println("DAOException with LOADIMGNAMES: "
851          + dex.getMessage());
852        out.writeObject(null);
853      }
854    }
855  
856  
857    /**
858     *  Asks to the LetterTemplate ejb for the service of loading loan
859     *  variables. It sends --to the proxy-- an ArrayList of ArrayLists
860     *  containing the information about all loan variables. If there is no
861     *  variables, null is sent back to the proxy. The internal ArrayList
862     *  contains [code, name, type] of a variable.
863     *
864     * @param out
865     * @exception ServletException
866     * @exception IOException
867     */
868    private void loadVariables(ObjectOutputStream out)
869       throws ServletException, IOException {
870      try {
871        debug.println("invokes loadVariables");
872        ArrayList al = letejb.loadVariables();
873  
874        debug.println("Variables size = " + al.size());
875        if(al.size() == 0) {
876          debug.println("There are no variables");
877          out.writeObject(null);
878        }
879        else {
880          out.writeObject(al);
881        }
882      }
883      catch(RemoteException rex) {
884        debug.println("RemoteException with LOADVARIABLES: " + rex.getMessage());
885        out.writeObject(null);
886      }
887      catch(DAOException dex) {
888        debug.println("DAOException with LOADVARIABLES: "
889          + dex.getMessage());
890        out.writeObject(null);
891      }
892    }
893  
894  
895    /**
896     *  Asks to the LetterTemplate ejb for the service of loading variable
897     *  formats. It sends --to the proxy-- an array of [code,description]
898     *  containing the information of all variable formats. If there is no
899     *  variable formats, null is sent back to the proxy.
900     *
901     * @param out
902     * @exception ServletException
903     * @exception IOException
904     */
905    private void loadVariableFormats(ObjectOutputStream out)
906       throws ServletException, IOException {
907      try {
908        debug.println("invokes loadVariableFormats");
909        CodeDescription[] cd = letejb.loadVariableFormats();
910  
911        debug.println("Formats size = " + cd.length);
912        if(cd.length == 0) {
913          debug.println("There are no formats");
914          out.writeObject(null);
915        }
916        else {
917          out.writeObject(cd);
918        }
919      }
920      catch(RemoteException rex) {
921        debug.println("RemoteException with LOADVARIABLEFORMATS: " + rex.getMessage());
922        out.writeObject(null);
923      }
924      catch(DAOException dex) {
925        debug.println("DAOException with LOADVARIABLEFORMATS: "
926          + dex.getMessage());
927        out.writeObject(null);
928      }
929    }
930  
931  
932    /**
933     *  Exit from editor usecase for 2 possible reasons: user request or
934     *  timeout
935     *
936     * @param req The standard request parameter
937     * @param resp The standard response parameter
938     * @param url Exit target
939     * @exception ServletException
940     * @exception IOException
941     */
942    private void exit(HttpServletRequest req, HttpServletResponse resp,
943                      String url)
944       throws ServletException, IOException {
945      try {
946        debug.println(url);
947        RequestDispatcher rd =
948          this.getServletContext().
949          getRequestDispatcher(url);
950        rd.forward(req, resp);
951      }
952      catch(Exception cfx) {
953        debug.println("Probably a casting problem with EXIT: "
954          + cfx.getMessage());
955      }
956    }
957  
958  
959    /**
960     * Brings to zero the inconsistent date offsets in a letter component.
961     *
962     * @param comp The component to be fixed.
963     * @param req Description of the Parameter
964     * @return A set containing the codes of the fixed variables.
965     * <DT><B>Side effects:</B><DD>
966     *      Sets the {@link #hashFields} attribute.
967     * @throws Exception Description of the Exception
968     */
969    private Set fixDateOffset(HttpServletRequest req, LetterComponent comp)
970       throws Exception {
971  
972      hashFields =
973        (Hashtable)req.getSession().getAttribute(WebKeys.SystemFields);
974      if(hashFields == null) {
975        try {
976          hashFields = letejb.loadFields();
977          req.getSession().setAttribute(WebKeys.SystemFields, hashFields);
978        }
979        catch(Exception ex) {
980          throw new Exception("Problems loading hash fields");
981        }
982      }
983  
984      //Calculates a list with codes of variables having inconsistent offsets.
985      ArrayList[] variables = comp.setOfVariables();
986      TemplateTransformer transf = new TemplateTransformer(variables, hashFields);
987      Set brokenVars = transf.offsetConsistency();
988  
989      //Brings to zero the inconsistent offsets.
990      if(!brokenVars.isEmpty()) {
991        Long broken = LetterTemplateGlobals.VOIDELTA;
992        Iterator it = comp.getTraceVariables().iterator();
993        while(it.hasNext()) {
994          ArrayList slot = (ArrayList)it.next();
995          Long varCode = (Long)slot.get(1);
996          if(brokenVars.contains(varCode)) {
997            slot.set(3, broken);
998          }
999        }
1000     }
1001 
1002     return brokenVars;
1003   }
1004 
1005 
1006   /**
1007    * Brings to zero the inconsistent date offsets in a letter Template.
1008    *
1009    * @param template The template to be fixed.
1010    * @param req Description of the Parameter
1011    * @return A set containing the codes of the fixed variables.
1012    * <DT><B>Side effects:</B><DD>
1013    *      based on {@link #fixDateOffset(HttpServletRequest,LetterComponent)}.
1014    * @throws Exception Description of the Exception
1015    */
1016   private Set fixDateOffset(HttpServletRequest req, Template template)
1017      throws Exception {
1018     Set brokenVars = fixDateOffset(req, template.getHeader());
1019 
1020     LetterComponent[] comps = {template.getBody(), template.getClosing()};
1021 
1022     for(int i = 0; i < comps.length; i++) {
1023       Set broken = fixDateOffset(req, comps[i]);
1024       Iterator it = broken.iterator();
1025       while(it.hasNext()) {
1026         Long varCode = (Long)it.next();
1027         brokenVars.add(varCode);
1028       }
1029     }
1030     return brokenVars;
1031   }
1032 
1033 
1034   /**
1035    * Calculates a text containing a comma separated list of the names of variables
1036    * in a Set.
1037    *
1038    * @param brokenVars a Set of var codes.
1039    * @return The specified String, or null if the set is void.
1040    */
1041   private String brokenVarNames(Set brokenVars) {
1042     if(brokenVars.isEmpty()) {
1043       return null;
1044     }
1045 
1046     StringBuffer sb = new StringBuffer();
1047     Iterator it = brokenVars.iterator();
1048     Field field = (Field)hashFields.get((Long)it.next());
1049     String varName = field.getDisplayName();
1050     sb.append('"');
1051     sb.append(varName);
1052     sb.append('"');
1053     while(it.hasNext()) {
1054       field = (Field)hashFields.get((Long)it.next());
1055       varName = field.getDisplayName();
1056       sb.append(", \"");
1057       sb.append(varName);
1058       sb.append('"');
1059     }
1060 
1061     return sb.toString();
1062   }
1063 
1064 
1065   /**
1066    *  Control time out in editor usecase: if timeout, inactivates the session
1067    *  and returns true if not timeout, reset timeout counter in lettertemplate and in
1068    *  Instantbank ear's and returns false. editor applet should invoke this
1069    *  method always before any other TemplateEditorServlet invokation and also
1070    *  in reaction to any user event. Example of invokation in editor applet:
1071    *  -----------------------------------------------------------------------
1072    *  Integer opCode = new Integer(LetterOp.CONTROLTIMEOUT); Serializable
1073    *  objs[] = {opCode}; in = TemplateEditorSender.postObjects(servlet, objs);
1074    *  boolean existsTimeout = ((Boolean)in.readObject()).booleanValue();
1075    *  in.close(); if (existsTimeout){ String homeurl =
1076    *  shortenUrl(getCodeBase().toExternalForm(),2); homeurl +=
1077    *  "lettertemplate/control_web/TimeOutPage.jsp";
1078    *  getAppletContext().showDocument (new URL(homeurl)); }
1079    *  ------------------------------------------------------------------------
1080    *
1081    * @param out answer stream to editor applet
1082    * @param request of web session
1083    * @param response
1084    * @exception IOException
1085    * @exception ServletException
1086    */
1087   private void controlTimeout(ObjectOutputStream out,
1088                               HttpServletRequest request, HttpServletResponse response)
1089      throws IOException, ServletException {
1090     boolean existsTimeout = false;
1091     HttpSession session = request.getSession();
1092     debug.println("Session is new ?=" + session.isNew());
1093 
1094     if(session.isNew()) {
1095       // server launched new session because of previous timeout
1096       debug.println("timeout in editor usecase");
1097       existsTimeout = true;
1098       request.getSession().invalidate();
1099     }
1100     out.writeObject(new Boolean(existsTimeout));
1101   }
1102 
1103 }
1104