KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > opensubsystems > core > application > ThickClient


1 /*
2  * Copyright (c) 2003 - 2007 OpenSubsystems s.r.o. Slovak Republic. All rights reserved.
3  *
4  * Project: OpenSubsystems
5  *
6  * $Id: ThickClient.java,v 1.20 2007/03/08 05:17:15 bastafidli Exp $
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; version 2 of the License.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */

21
22 package org.opensubsystems.core.application;
23
24 import java.io.IOException JavaDoc;
25 import java.util.HashSet JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.LinkedHashMap JavaDoc;
28 import java.util.Map JavaDoc;
29 import java.util.Properties JavaDoc;
30 import java.util.Set JavaDoc;
31 import java.util.logging.Level JavaDoc;
32 import java.util.logging.Logger JavaDoc;
33
34 import org.apache.commons.cli.BasicParser;
35 import org.apache.commons.cli.CommandLine;
36 import org.apache.commons.cli.CommandLineParser;
37 import org.apache.commons.cli.HelpFormatter;
38 import org.apache.commons.cli.Option;
39 import org.apache.commons.cli.OptionGroup;
40 import org.apache.commons.cli.Options;
41 import org.apache.commons.cli.ParseException;
42 import org.mortbay.http.HttpServer;
43 import org.mortbay.util.MultiException;
44 import org.opensubsystems.core.error.OSSConfigException;
45 import org.opensubsystems.core.error.OSSDynamicClassException;
46 import org.opensubsystems.core.error.OSSException;
47 import org.opensubsystems.core.persist.db.Database;
48 import org.opensubsystems.core.persist.db.DatabaseImpl;
49 import org.opensubsystems.core.util.ClassFactory;
50 import org.opensubsystems.core.util.Config;
51 import org.opensubsystems.core.util.GlobalConstants;
52 import org.opensubsystems.core.util.Log;
53 import org.opensubsystems.core.util.ProductInfo;
54
55 /**
56  * The main class which represents application that executes on a client
57  * computer. It provides framework for various modules to coexists together
58  * on the client computer. It's responsibility is to instantiate, coordinate and
59  * destroy these modules. Modules are specified in the configuration files using
60  * numbered properties, such as
61  *
62  * oss.thickclient.module.0=full classname for module 0
63  * oss.thickclient.module.1=full classname for module 1
64  * ...
65  *
66  * This class is independent of any GUI technology (such as SWT or AWT) used to
67  * actually construct the thick client. It defers all methods, which may depend
68  * of any GUI technology to the ThickClientGui interface. On the other hand
69  * this class is not an interface just because there has to be a class, which
70  * implements main method which launches the application.
71  *
72  * The application which will be started must be specified in te configuration
73  * files, using property
74  * [full classname for ThickClient class]=full classname for application to start
75  *
76  * Thick client embeds by default server since most modern enterprise
77  * applications require some kind of support for inter-application communication
78  * and therefore act both as clients and servers.
79  *
80  * @version $Id: ThickClient.java,v 1.20 2007/03/08 05:17:15 bastafidli Exp $
81  * @author Miro Halas
82  * @code.reviewer Miro Halas
83  * @code.reviewed 1.17 2006/04/05 04:56:57 bastafidli
84  */

85 public class ThickClient extends Server
86 {
87    // Configuration settings ///////////////////////////////////////////////////
88

89    /**
90     * This is used to name parameters such as oss.thickclient.module.0,
91     * oss.thickclient.module.1. These parameters are used to specify modules
92     * which are running inside of this thick client.
93     */

94    public static final String JavaDoc GUI_MODULE_PREFIX = "oss.thickclient.module.";
95    
96    // Attributes ///////////////////////////////////////////////////////////////
97

98    /**
99     * Default GUI technology to use for instantiation of thick client.
100     * TODO: Configure: Allow to specify this variable from the command line.
101     */

102    protected static String JavaDoc s_strDefaultGUITechnology = "SWT";
103    
104    /**
105     * Position where to display GUI on the screen. It should be one of the
106     * GUI_XXX constants.
107     */

108    protected int m_iScreenPosition;
109
110    /**
111     * If true then the window will be displayed with fixed size and cannot be
112     * resized. The default fixed size is 1024x768.
113     * TODO: Configure: Make this fixed size configurable.
114     */

115    protected boolean m_bFixedSize;
116    
117    /**
118     * If true then hide cursor. (e.g. if we are on the touchscreen).
119     */

120    protected boolean m_bHideCursor;
121    
122    /**
123     * This flag is true when gui is being stopped.
124     */

125    protected boolean m_bStoppingGui;
126    
127    /**
128     * Map where key is the module name (String) and value is the module
129     * (ThickClientModule) itself.
130     */

131    protected Map JavaDoc m_modules;
132    
133    /**
134     * Name of the module from m_modules, which is currently active.
135     */

136    protected String JavaDoc m_strActiveModuleName;
137    
138    /**
139     * Collection of module names, which were previously at least once active.
140     */

141    protected Set JavaDoc m_strPreviouslyActiveModules;
142    
143    /**
144     * This flag is set after modules are created.
145     */

146    protected boolean m_bModulesCreated;
147    
148    /**
149     * Gui representing the thick client application.
150     */

151    protected ThickClientGui m_gui;
152    
153    // Cached values ////////////////////////////////////////////////////////////
154

155    /**
156     * Logger for this class
157     */

158    private static Logger JavaDoc s_logger = Log.getInstance(ThickClient.class);
159    
160    /**
161     * Default thick client class to instantiate
162     */

163    protected static Class JavaDoc s_clsDefaultThickClient = ThickClient.class;
164
165    // Constructors /////////////////////////////////////////////////////////////
166

167    /**
168     * Construct instance of the thick client application.
169     */

170    public ThickClient(
171    )
172    {
173       this(new ProductInfo()
174            {
175               public String JavaDoc getProductName()
176               {
177                  return "Generic application";
178               }
179
180               public String JavaDoc getProductVersion()
181               {
182                  return "1.0";
183               }
184
185               public String JavaDoc getProductCreator()
186               {
187                  return "OpenSubsystems s.r.o.";
188               }
189
190               public String JavaDoc getCopyright()
191               {
192                  return "Copyright (c) 2003 - 2007 OpenSubsystems s.r.o." +
193                         " Slovak Republic. All rights reserved.";
194               }
195            });
196    }
197    
198    /**
199     * Construct instance of the thick client application.
200     *
201     * @param product - information about product which is running this
202     * application, this way we will force every application to
203     * create and publish this information in uniform way
204     */

205    public ThickClient(
206       ProductInfo product
207    )
208    {
209       super(product);
210       
211       m_iScreenPosition = ThickClientGui.GUI_FULLSCREEN;
212       m_bFixedSize = false;
213       m_bHideCursor = false;
214       // We need go use LinkedHashMap so that we maintain the orde in which
215
// the modules were specified in the configuration file
216
m_modules = new LinkedHashMap JavaDoc();
217       m_strPreviouslyActiveModules = new HashSet JavaDoc();
218       m_bModulesCreated = false;
219    }
220
221    /**
222     * The defaul implementation of the main method. It doesn't do anything much,
223     * just starts the application.
224     *
225     * @param args - arguments passed from command line
226     */

227    public static void main(
228       String JavaDoc[] args
229    )
230    {
231       ThickClient client;
232
233       // Parse arguments
234
Option help;
235       Option rightSide;
236       Option leftSide;
237       Option fixedSize;
238       Option noCursor;
239       OptionGroup screenPosition;
240       Options cmdLineoptions = new Options();
241       CommandLineParser parser = new BasicParser();
242       CommandLine cmdLine;
243       
244       // This really means that user can specify -h or --help
245
help = new Option("h", "help", false, "Print this message");
246       // TODO: Configure: Make the fixed size configurable.
247
fixedSize = new Option("f", "fixed", false,
248             "Display the window with fixed size 1024x768");
249       rightSide = new Option("r", "right", false,
250             "Display the screen on the right side of the desktop or right monitor");
251       leftSide = new Option("l", "left", false,
252             "Display the screen on the left side of the desktop or left monitor");
253       noCursor = new Option("c", "cursor", false,
254             "Hide the cursor over the application (good for touchscreen)");
255       screenPosition = new OptionGroup();
256       screenPosition.addOption(rightSide);
257       screenPosition.addOption(leftSide);
258       cmdLineoptions.addOption(help);
259       cmdLineoptions.addOption(noCursor);
260       cmdLineoptions.addOption(fixedSize);
261       cmdLineoptions.addOptionGroup(screenPosition);
262       
263       try
264       {
265          cmdLine = parser.parse(cmdLineoptions, args);
266          if (cmdLine.hasOption('h'))
267          {
268             HelpFormatter helpFormtter = new HelpFormatter();
269             helpFormtter.printHelp(80, "ThickClient [Options]", "",
270                                    cmdLineoptions, "");
271          }
272          else
273          {
274             int iScreenPosition = ThickClientGui.GUI_FULLSCREEN;
275             
276             // TODO: ThickClient: Add suuport for GUI_ANYWHERE
277
if (cmdLine.hasOption('r'))
278             {
279                iScreenPosition = ThickClientGui.GUI_RIGHTSCREEN;
280             }
281             else if (cmdLine.hasOption('l'))
282             {
283                iScreenPosition = ThickClientGui.GUI_LEFTSCREEN;
284             }
285             
286             if (iScreenPosition != ThickClientGui.GUI_FULLSCREEN)
287             {
288                // There can be multiple GUI's running at the same time so
289
// generate unique server id to prevent one instance deleting
290
// sessions of other. The assumption is that if GUI is running
291
// on a full screen this is to prevent user from executing other
292
// applications
293

294                // TODO: ThickClient: This doesn't look right because it assumes
295
// that we do not have two applications running on the same
296
// screen position. We may want to generalize it and make the
297
// additional number globally unique, e.g. port number (since two
298
// servers cannot listen to the same port numbers). The problem
299
// is that at this time we do not know the server port numbers
300
// since the server wasn't started yet. The important thing is
301
// that the number should be repeatable between restarts so that
302
// we can cleanup session from prevoius restart
303

304                ServerId.getInstance().setServerId(
305                                          ServerId.getInstance().getServerId()
306                                          + "-" + iScreenPosition);
307             }
308             
309             // Get the application specific instance of the thick client
310
// This is done dynamically so that application can have their own
311
// specific look, feel and behavior, etc.
312
client = getThickClientInstance();
313             client.initScreenOptions(iScreenPosition, cmdLine.hasOption('f'),
314                                     cmdLine.hasOption('c'));
315             try
316             {
317                // Now start the embedded server. The server will dictate
318
// the application lifecycle and will actually initialize, start
319
// and when appropriate also destroy the application.
320
startServer(client);
321             }
322             catch (Throwable JavaDoc thr)
323             {
324                s_logger.log(Level.SEVERE, "Cannot start the server.", thr);
325             }
326             finally
327             {
328                // This will cause server to be stopped by invoking the shutdown
329
// hook defined in the parent class.
330
// TODO: Improve: Figure out how to remove this call. When the
331
// GUI exists we should be able to just stop the server and let
332
// the VM exit
333
stopServer(client);
334             }
335          }
336       }
337       catch (OSSException ossExc)
338       {
339          HelpFormatter helpFormtter = new HelpFormatter();
340          System.out.println(ossExc.getMessage());
341          // TODO: Improve: ThickClient here should be customizable with the name
342
// of the application actually executed
343
helpFormtter.printHelp(80, "ThickClient [Options]", "",
344                                 cmdLineoptions, "");
345       }
346       catch (ParseException prseExc)
347       {
348          HelpFormatter helpFormtter = new HelpFormatter();
349          System.out.println(prseExc.getMessage());
350          // TODO: Improve: ThickClient here should be customizable with the name
351
// of the application actually executed
352
helpFormtter.printHelp(80, "ThickClient [Options]", "",
353                                 cmdLineoptions, "");
354       }
355    }
356
357    /**
358     * Get gui for this client.
359     *
360     * @return ThinkClientGui
361     */

362    public ThickClientGui getGui(
363    )
364    {
365       return m_gui;
366    }
367    
368    /**
369     * If true then the window will be displayed with fixed size and cannot be
370     * resized. The default fixed size is 1024x768.
371     *
372     * @return boolean
373     */

374    public boolean isFixedSize()
375    {
376       return m_bFixedSize;
377    }
378
379    /**
380     * Position where to display GUI on the screen. It should be one of the
381     * GUI_XXX constants.
382     *
383     * @return int
384     */

385    public int getScreenPosition()
386    {
387       return m_iScreenPosition;
388    }
389
390    /**
391     * {@inheritDoc}
392     */

393    public void init(
394    ) throws OSSException,
395             IOException JavaDoc
396    {
397       ClassFactory classFactory;
398       
399       classFactory = new ThickClientDependentClassFactory(s_strDefaultGUITechnology);
400       m_gui = (ThickClientGui)classFactory.createInstance(ThickClientGui.class);
401       m_gui.init(this);
402       
403       super.init();
404    }
405
406    /**
407     * {@inheritDoc}
408     */

409    public void start(
410    ) throws MultiException,
411             OSSException
412    {
413       // First start the underlying server
414
super.start();
415             
416       // TODO: ThickClient: Make this configurable, since we will also have
417
// applications which do not have local database and instead they connect
418
// to server to access their information. The applications shouldn't
419
// be starting local database.
420

421       // The applications we are interested in are database based applications
422
// so start the database since this is still part of the backend services
423
s_logger.fine("Starting default thick client database.");
424       Database dbDatabase;
425          
426       dbDatabase = DatabaseImpl.getInstance();
427       dbDatabase.start();
428       s_logger.fine("Default thick client database started.");
429       
430       // Now when the optional database should be started, start the thick
431
// client application itself
432
startThickClient();
433    }
434     
435    /**
436     * {@inheritDoc}
437     */

438    public void stop(
439    ) throws OSSException,
440             InterruptedException JavaDoc
441    {
442       try
443       {
444          stopThickClient();
445          
446       // TODO: ThickClient: This needs to be done only if there is a local database
447
// so make it dependent on the local database configuration or expose a
448
// flag from the parent class or even better ask if the local database is
449
// running, there is already a method for it (see use of
450
// getInstanceIfStarted in SecureThickClient.stopThickClient).
451
s_logger.fine("Stopping default thick client database.");
452          Database dbDatabase;
453             
454          dbDatabase = DatabaseImpl.getInstance();
455          dbDatabase.stop();
456          s_logger.fine("Default thick client database stopped.");
457       }
458       finally
459       {
460          // Stop the underlying server
461
super.stop();
462       }
463    }
464
465    /**
466     * Activate specified module.
467     *
468     * @param strModuleName - name of the module to activate.
469     */

470    public void activateModule(
471       String JavaDoc strModuleName
472    )
473    {
474       // Allow to activate only if the modules were created and not yet destroyed
475
if ((m_bModulesCreated) && ((m_strActiveModuleName == null)
476          || (!m_strActiveModuleName.equals(strModuleName))))
477       {
478          // Either no module was active or user is switching from module to module
479
ThickClientModule oldModule = null;
480          ThickClientModule newModule = null;
481          boolean bExistingModule;
482          
483          // We need to check this first because once activated we cannot get
484
// the history
485
bExistingModule = m_strPreviouslyActiveModules.contains(strModuleName);
486          
487          // Pasivate the currently active module
488
if (m_strActiveModuleName != null)
489          {
490             oldModule = (ThickClientModule)m_modules.get(m_strActiveModuleName);
491             if (GlobalConstants.ERROR_CHECKING)
492             {
493                assert oldModule != null
494                       : "Cannot find module " + m_strActiveModuleName;
495             }
496             pasivateModule(oldModule);
497          }
498          
499          // Activate the new module
500
newModule = (ThickClientModule)m_modules.get(strModuleName);
501          if (GlobalConstants.ERROR_CHECKING)
502          {
503             assert newModule != null : "Cannot find module " + strModuleName;
504          }
505          if (activateModule(newModule, false))
506          {
507             // If the module was previously active, we need to refresh it's information
508
if (bExistingModule)
509             {
510                // When we are switching to already existing module, the information
511
// displayed may have changed while being in the other module.
512
// Therefore refresh the screen with most current info.
513
newModule.refresh();
514             }
515          }
516          else
517          {
518             if ((oldModule != null) && (!m_bStoppingGui))
519             {
520                // We need to reactivate the previously active module but only
521
// if the gui is not going down
522
activateModule(oldModule, true);
523             }
524          }
525       }
526    }
527
528    /**
529     * Check if it is OK to stop the gui. This is abstract since the way we ask
530     * user is usually implementation specific.
531     *
532     * @return boolean - true - the gui can be stopped
533     * false - the gui cannot be stopped at this time
534     */

535    public boolean canStopGUI(
536    )
537    {
538       boolean bReturn;
539       
540       bReturn = (ThickClientGui.MESSAGE_ANSWER_YES.equals(m_gui.displayMessage(
541                    ThickClientGui.MESSAGE_TITLE_QUESTION,
542                    "Are you sure you want to exit the system?",
543                    ThickClientGui.MESSAGE_STYLE_YES_NO_QUESTION)));
544       
545       return bReturn;
546    }
547    
548    /**
549     * Call this method to stop the GUI. Derived classes may perform some
550     * activities which require the GUI to be present but must be execute them
551     * only after user confirmed that he really wants to stop or exit the
552     * application.
553     *
554     * @return boolean - true - the gui was sucessfully stopped
555     * false - an error has occured while stopping gui
556     */

557    public boolean stopGUI(
558    )
559    {
560       // Set this flag so we know in asynchronous methods that the gui is going
561
// down
562
m_bStoppingGui = true;
563       return true;
564    }
565
566    // Helper methods ///////////////////////////////////////////////////////////
567

568    /**
569     * {@inheritDoc}
570     */

571    protected void addWebApplications(
572       HttpServer hsServer
573    )
574    {
575       // Many thick clients do not have web applications packaged with them
576
// so define this method as empty and let the derived class override
577
// it if there is any
578
}
579
580    /**
581     * Get instance of thick client application to start. The instance is
582     * determined dynamically by looking at class, which is configured as
583     * implementor of ThickClient.
584     *
585     * @return ThickClient - thick client to start
586     * @throws OSSException - an error has occured
587     */

588    protected static ThickClient getThickClientInstance(
589    ) throws OSSException
590    {
591       ClassFactory classFactory;
592       ThickClient client;
593       
594       classFactory = new ThickClientDependentClassFactory(s_strDefaultGUITechnology);
595       client = (ThickClient)classFactory.createInstance(s_clsDefaultThickClient);
596       
597       return client;
598    }
599
600    /**
601     * Initialize position and size related parameters.
602     *
603     * @param iScreenPosition - position where to display GUI on the screen,
604     * one of the GUI_XXX constants
605     * @param bFixedSize - if true then the window will be displayed with fixed
606     * size 1024x768
607     * @param bHideCursor - hide cursor (e.g. if we are on the touchscreen)
608     */

609    protected void initScreenOptions(
610       int iScreenPosition,
611       boolean bFixedSize,
612       boolean bHideCursor
613    )
614    {
615       m_iScreenPosition = iScreenPosition;
616       s_logger.config("Screen position = " + m_iScreenPosition);
617       m_bFixedSize = bFixedSize;
618       s_logger.config("Fixed size screen = " + m_bFixedSize);
619       m_bHideCursor = bHideCursor;
620       s_logger.config("Hide cursor = " + m_bHideCursor);
621    }
622
623    /**
624     * Start the thick client. This method should be invoked at a point when the
625     * backend (if any) is already started and therefore it is safe to start the
626     * thick client gui or background tasks to connect to the these. Derived
627     * classes may overide this method to initialize any background tasks or
628     * perform any setup activitied before the gui is started.
629     *
630     * @throws OSSException - an error has occured
631     */

632    protected void startThickClient(
633    ) throws OSSException
634    {
635       // The only thing we can do to start thick client is to start the gui
636
startGui();
637    }
638
639    /**
640     * Stop the thick client. This method is invoked at a point when the GUI
641     * was already closed so the application is no longer already for user.
642     * The derived classes may override this method to stop any background tasks.
643     *
644     * @throws OSSException - an error has occured
645     */

646    protected void stopThickClient(
647    ) throws OSSException
648    {
649        // Nothing to do at this point since there are no background tasks
650
}
651    
652    /**
653     * Start the GUI portion of the thick client application. By this time the
654     * backend/background tasks should be already started.
655     *
656     * @throws OSSException - an error has occured
657     */

658    protected void startGui(
659    ) throws OSSException
660    {
661       try
662       {
663          // Initialize any resources which are required by gui
664
m_gui.createDisplayResources(m_bHideCursor);
665          // Display the gui using previously initialized resources in separate
666
// method so that if application had a different way how to display
667
// gui then it can change this behavior
668
displayGUI();
669       }
670       finally
671       {
672          // Properly release all display resources
673
m_gui.destroyDisplayResources();
674       }
675    }
676    
677    /**
678     * Display the gui using previously initialized resources. This is done in
679     * separate method so that if application had a different way how to display
680     * gui then it can change this behavior.
681     *
682     * @throws OSSException - an error has occured
683     */

684    protected void displayGUI(
685    ) throws OSSException
686    {
687       try
688       {
689          s_logger.fine("Creating main window.");
690          m_gui.createMainWindow();
691          s_logger.fine("Creating modules.");
692          createModules();
693          s_logger.fine("Creating client area.");
694          m_gui.createClientArea();
695          s_logger.fine("Displaying main window.");
696          m_gui.displayMainWindow(m_iScreenPosition, m_bFixedSize);
697          s_logger.fine("Starting interaction with user.");
698          m_gui.interactWithUser();
699          s_logger.fine("Finished interation with user.");
700       }
701       finally
702       {
703          s_logger.fine("Destroying client area.");
704          m_gui.destroyClientArea();
705          s_logger.fine("Destroying modules.");
706          destroyModules();
707          s_logger.fine("Destroying main window.");
708          m_gui.destroyMainWindow();
709          s_logger.fine("Cleanup is finished.");
710          // We are done with stopping the gui, we can reset the flag
711
m_bStoppingGui = false;
712       }
713    }
714    
715    /**
716     * Create modules, which should be available in the thick client application.
717     * The application is not fully constructed yet therefore the module should
718     * not attempt to access any part of the user interface.
719     *
720     * @throws OSSException - an error has occured
721     */

722    protected void createModules(
723    ) throws OSSException
724    {
725       // The default implementation reads the modules from the configuration file
726
Properties JavaDoc settings;
727       String JavaDoc strModuleClassName;
728       int iIndex = 0;
729       ThickClientModule module;
730       ClassFactory classFactory = new ThickClientDependentClassFactory(
731                                          s_strDefaultGUITechnology);
732       
733       // Read configuration properties to determine what modules are available
734
settings = Config.getInstance().getPropertiesSafely();
735       try
736       {
737          do
738          {
739             strModuleClassName = settings.getProperty(GUI_MODULE_PREFIX + iIndex);
740             if ((strModuleClassName != null) && (strModuleClassName.length() > 0))
741             {
742                iIndex++;
743                try
744                {
745                   s_logger.fine("Read module name " + strModuleClassName);
746                   // Use class factory to instantiate the module so that based on
747
// current GUI technology we instantiate the correct module
748
module = (ThickClientModule)classFactory.createInstance(strModuleClassName);
749                   s_logger.fine("Instantiated module " + strModuleClassName);
750                   m_modules.put(module.getName(), module);
751                   // Do not initialize module at this point since we don't know if the module
752
// will ever be accessed. Initialize it lazily when it is accessed.
753
// module.init(this);
754
}
755                catch (OSSDynamicClassException ossExc)
756                {
757                   s_logger.warning("Module " + strModuleClassName
758                                    + " cannot be instantiated.");
759                   
760                }
761             }
762          }
763          while (strModuleClassName != null);
764          m_bModulesCreated = true;
765       }
766       catch (SecurityException JavaDoc eSec)
767       {
768          throw new OSSConfigException(
769                       "Unexpected error has occured while creating modules.",
770                       eSec);
771       }
772       catch (IllegalArgumentException JavaDoc eIllArg)
773       {
774          throw new OSSConfigException(
775                       "Unexpected error has occured while creating modules.",
776                       eIllArg);
777       }
778       
779       m_gui.createModules(m_modules);
780    }
781
782    /**
783     * Destroy modules, which were created for the thick client application.
784     */

785    protected void destroyModules(
786    )
787    {
788       if (!m_modules.isEmpty())
789       {
790          Iterator JavaDoc modules;
791          Map.Entry JavaDoc entry;
792          
793          for (modules = m_modules.entrySet().iterator(); modules.hasNext();)
794          {
795             entry = (Map.Entry JavaDoc)modules.next();
796             ((ThickClientModule)entry.getValue()).destroy();
797          }
798       }
799       m_bModulesCreated = false;
800       
801       m_gui.destroyModules(m_modules);
802       
803       m_modules.clear();
804       m_strActiveModuleName = null;
805       m_strPreviouslyActiveModules.clear();
806    }
807    
808    /**
809     * Pasivate the specified module so that it is not available for user
810     * interaction anymore.
811     *
812     * @param module - module to pasivate
813     */

814    protected void pasivateModule(
815       ThickClientModule module
816    )
817    {
818       s_logger.finer("Pasivating module " + module.getName());
819       module.pasivate();
820       // No module is active at this time
821
m_strActiveModuleName = null;
822       
823       m_gui.pasivateModule(module);
824    }
825    
826    /**
827     * Activate specified module so that it is available for user interaction.
828     *
829     * @param module - module to activate
830     * @param bReactivate - this is true if the module was pasivated but it is
831     * being immediately activated again because the other
832     * module which caused it's pasivation coun't be
833     * activated again. This is false if some other module
834     * was active and now this module is being activated.
835     * @return boolean - true if sucessfully activated
836     * false if cannot be activated and either the previously
837     * active module should remain active or no module should
838     * be active
839     */

840    protected boolean activateModule(
841       ThickClientModule module,
842       boolean bReactivate
843    )
844    {
845       boolean bReturn = false;
846       boolean bExistingModule;
847       
848       try
849       {
850          // We need to check this first because once activated we cannot get
851
// the history
852
bExistingModule = m_strPreviouslyActiveModules.contains(module.getName());
853          if (!bExistingModule)
854          {
855             // This is the first time the module is being accessed so initialize it
856
s_logger.finer("Initializing module " + module.getName());
857             module.init(this);
858          }
859          s_logger.finer("Activating module " + module.getName());
860          bReturn = module.activate(bReactivate);
861          if (bReturn)
862          {
863             // Change these variables only if the module was sucessfully activated
864
m_strActiveModuleName = module.getName();
865             m_strPreviouslyActiveModules.add(module.getName());
866             m_gui.activateModule(module);
867          }
868       }
869       catch (OSSException ossExc)
870       {
871          s_logger.log(Level.WARNING,
872                       "An unexpected error has occured while activating module "
873                       + module.getName(),
874                       ossExc);
875          m_gui.displayMessage(ThickClientGui.MESSAGE_TITLE_ERROR,
876                   "An unexpected error has occured while activating module "
877                   + module.getName() + ": " + ossExc.getMessage(),
878                   ThickClientGui.MESSAGE_STYLE_ERROR);
879       }
880       
881       return bReturn;
882    }
883 }
884
Popular Tags