View Javadoc

1   package com.explosion.expf;
2   
3   /*
4    * =============================================================================
5    * 
6    * Copyright 2004 Stephen Cowx
7    * 
8    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
9    * use this file except in compliance with the License. You may obtain a copy of
10   * the License at
11   * 
12   * http://www.apache.org/licenses/LICENSE-2.0
13   * 
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17   * License for the specific language governing permissions and limitations under
18   * the License.
19   * 
20   * =============================================================================
21   */
22  
23  import java.awt.Color;
24  import java.awt.Component;
25  import java.awt.HeadlessException;
26  import java.io.File;
27  import java.io.IOException;
28  import java.net.URL;
29  import java.util.ArrayList;
30  import java.util.Collections;
31  import java.util.Date;
32  import java.util.HashMap;
33  import java.util.Iterator;
34  import java.util.List;
35  import java.util.Map;
36  import java.util.Properties;
37  import java.util.StringTokenizer;
38  import java.util.Vector;
39  import java.util.prefs.Preferences;
40  
41  import javax.help.HelpBroker;
42  import javax.help.HelpSet;
43  import javax.swing.JFrame;
44  import javax.swing.JInternalFrame;
45  import javax.swing.JOptionPane;
46  import javax.swing.SwingUtilities;
47  import javax.swing.UIManager;
48  
49  import org.apache.log4j.ConsoleAppender;
50  import org.apache.log4j.Level;
51  import org.apache.log4j.LogManager;
52  import org.apache.log4j.Logger;
53  import org.apache.log4j.PatternLayout;
54  import org.apache.log4j.RollingFileAppender;
55  
56  import com.explosion.expf.preferences.SystemPreferences;
57  import com.explosion.utilities.GeneralConstants;
58  import com.explosion.utilities.GeneralUtils;
59  import com.explosion.utilities.PropertiesUtils;
60  import com.explosion.utilities.dialog.SplashScreen;
61  import com.explosion.utilities.exception.ExceptionManagerFactory;
62  import com.explosion.utilities.preferences.Preference;
63  
64  /***
65   * This is the interface for an application
66   * 
67   * @author Stephen Cowx Date created:@07-Feb-2003
68   */
69  public class Application
70  {
71  
72      private static Application instance;
73      private static SplashScreen splashScreen = null;
74  
75      private static org.apache.log4j.Logger log = org.apache.log4j.LogManager.getLogger(Application.class);
76  
77      /* Attributes */
78      private static Properties properties;
79  
80      /* ApplicationFrame */
81      private ExpFrame frame;
82  
83      /* Modules */
84      private Vector modulesVector = new Vector();
85      private HashMap modulesHash = new HashMap();
86  
87      /* Help */
88      private HelpSet helpSet = null;
89      private HelpBroker helpBroker = null;
90  
91      /* Cookies */
92      private HashMap globalCookies = new HashMap();
93      private HashMap localCookies = new HashMap();
94  
95      /* Component level cookie control */
96      private HashMap activeComponents = new HashMap();
97      private HashMap componentCookies = new HashMap();
98      private HashMap componentTracker = new HashMap();
99  
100     /* MenuMap */
101     private static Vector menuMap;
102     
103     private String applicationPrefix ;
104     
105     /***
106      * The module properties map contains a set of Map;s keyed in name, one for each loaded module.  It contains 
107      * all of the properties speficied for a module in the expf.properties
108      */
109     private Map propertiesMap;
110     
111     private boolean isAlive = false;
112 
113     /***
114      * Constructor, checks to see that it is the only instance
115      */
116     public Application() throws Throwable
117     {
118         if (instance != null)
119             throw new Exception("There is already an instance of an Application within this virtual machine");
120         else
121             instance = this;
122         
123         isAlive = true;
124     }
125     
126     /***
127      * This is the main metho which can be used for starting up an instance o fan application
128      * The preferred method is to use the Bootstrap library to Boot the app
129      * @param args
130      */
131     public static void main(String[] args)
132     {
133         try
134         {
135             if(args.length < 1)
136                throw new Exception("Application prefix needs to be specified as a command line argument.");
137             Application application = new Application();
138             application.init(args[0]);
139         }
140         catch (Throwable e)
141         {
142             ExceptionManagerFactory.getExceptionManager().manageException(e,"Exception caught while ");
143         }
144     }
145     
146     /***
147      * Initialises the application
148      * @param applicationPrefix
149      * @throws Exception
150      */
151     public void init(String applicationPrefix) throws Exception
152     {
153         this.applicationPrefix = applicationPrefix;
154         if (!GeneralUtils.checkJREVersion(1.4))
155         {
156             UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
157 
158             System.out.println("");
159             System.out.println("Incorrect Java Virtual Machine version");
160             System.out.println("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-");
161             System.out.println("");
162             System.out.println("This application can only be run using a Java Virtual Machine");
163             System.out.println("whose version is 1.4 or greater.  You can download a 1.4 JVM");
164             System.out.println("for your platform from http://java.sun.com/getjava/index.html");
165             System.out.println("");
166             System.out.println("General info about your current JVM");
167             System.out.println("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=");
168             System.out.println("java.vm.version : " + System.getProperty("java.vm.version"));
169             System.out.println("java.vm.specification.version : " + System.getProperty("java.vm.specification.version"));
170             System.out.println("java.specification.version : " + System.getProperty("java.specification.version"));
171             System.out.println("java.class.version : " + System.getProperty("java.class.version"));
172             System.out.println("");
173             System.out.println("For more information or assistance contact support@explosion-it.net");
174             JOptionPane.showMessageDialog(null, "This application can only be run using a Java Virtual Machine whose version is  " + GeneralConstants.LS
175                     + "1.4 or greater.  You can download a 1.4 JVM for your platform from  " + GeneralConstants.LS + "http://java.sun.com/getjava/index.html. "
176                     + GeneralConstants.LS + GeneralConstants.LS + "For more information or assistance contact support@explosion-it.net",
177                     "Incorrect Java Virtual Machine version", JOptionPane.ERROR_MESSAGE);
178             System.exit(0);
179         }
180 
181         /*  Look up system root preference */
182         Preferences prefs = Preferences.userRoot().node(applicationPrefix);
183         
184         /* Initialise the logging preferences */
185         SystemPreferences.initilaiseloggingPreferences(prefs);
186         
187         /* Start the logging manager */
188         initialiseLogging();
189         
190         log.debug("Logging initialised");
191         
192         /* Fetch the properties file */
193         properties = PropertiesUtils.loadPropertiesFromClasspath("expf.properties", this.getClass().getClassLoader());
194 
195         if (properties == null)
196             throw new Exception("Mandatory manifest entry " + ExpConstants.EXPF_APPLICATION + "does not exist");
197 
198         if (properties.getProperty(ExpConstants.EXPF_APP_NAME) == null)
199             throw new Exception("Properties file 'expf.properties' does not have mandatory property '" + ExpConstants.EXPF_APP_NAME + "'.");
200         if (properties.getProperty(ExpConstants.EXPF_APP_VERSION) == null)
201             throw new Exception("Manifest entry 'expf.properties' does not have mandatory property '" + ExpConstants.EXPF_APP_VERSION + "'.");
202         if (properties.getProperty(ExpConstants.EXPF_APP_PREFIX) == null)
203             throw new Exception("Manifest entry 'expf.properties' does not have mandatory property '" + ExpConstants.EXPF_APP_PREFIX + "'.");
204         if (properties.getProperty(ExpConstants.EXPF_APP_HELP_FILE) == null)
205             throw new Exception("Manifest entry 'expf.properties' does not have mandatory property '" + ExpConstants.EXPF_APP_HELP_FILE + "'.");
206 
207         /* Initialise the remaining preferences */
208         SystemPreferences.initialisePreferences(prefs, properties);
209          
210          /* Extract the menuMap if there is one. */
211         String menuString = properties.getProperty(ExpConstants.EXPF_APP_MENU_MAP);
212         if (menuString != null)
213         {
214             menuMap = new Vector();
215             StringTokenizer tokenizer = new StringTokenizer(menuString, ",");
216             while (tokenizer.hasMoreTokens())
217                 menuMap.addElement(tokenizer.nextToken());
218         }
219 
220         log.debug("Showing splashscreen");
221         String splashScreenImage = getSplashImage();
222         splashScreen = new SplashScreen(splashScreenImage, Color.white);
223         
224         /* Initialise preferences */
225         splashScreen.updateText("Initialising environment...");
226         File file = new File(System.getProperty("user.home") + System.getProperty("file.separator") + "." + properties.getProperty(ExpConstants.EXPF_APP_PREFIX));
227         if (!file.exists())
228             file.mkdirs();
229 
230         /* Initialise user dir to last used directory last time */
231         System.setProperty("user.dir", (String) SystemPreferences.getPreference(ExpConstants.LASTDIR).getValue());
232         updateLookAndFeel();
233 
234         /* Initialise exception listener */
235         splashScreen.updateText("Initialising exception handling...");
236 
237         ExceptionManagerFactory.getExceptionManager().addExceptionHandler(new ExpExceptionHandler());
238 
239         splashScreen.updateText("Creating application base...");
240         try
241         {
242         	log.debug("Initialising application frame");
243         	String title = (String) SystemPreferences.getPreference(ExpConstants.EXPF_APP_NAME).getValue();
244             String iconImage = getIconImage();
245             frame = new ExpFrame(iconImage, title);
246             frame.init();
247         }
248         catch (Exception ex)
249         {
250             com.explosion.utilities.exception.ExceptionManagerFactory.getExceptionManager().manageException(ex, "Exception caught while initialising Application Frame.");
251             throw ex;
252         }
253 
254         /* Initialise help */
255         splashScreen.updateText("Initialising application help...");
256         frame.getRootPane().addKeyListener(frame.getListener());
257 
258         /* Initialise all of the modules */
259         initialiseModules();
260 
261         /* Kill the gumpf */
262         splashScreen.dispose();
263 
264         /* Show the application */
265         frame.show();
266     }
267 
268 
269     /***
270      * Returns the Application instance
271      */
272     public static Application getInstance()
273     {
274         return instance;
275     }
276 
277     /***
278      * Returns the module managers
279      * 
280      * @return a vector containing all of the ModuleManagers initialised for
281      *         this application
282      */
283     public static Vector getModules()
284     {
285         if (instance != null)
286             return instance.modulesVector;
287         else
288             return null;
289     }
290 
291     /***
292      * Returns a specific module manager whose name matches the given name
293      * 
294      * @return a ExpModuleManager
295      */
296     public static ExpModuleManager getModule(String name)
297     {
298         if (instance != null)
299             return (ExpModuleManager) instance.modulesHash.get(name);
300         else
301             return null;
302     }
303 
304     /***
305      * return the cookie database (A map)
306      * 
307      * @return globalCookies
308      */
309     public static Map getGlobalCookies()
310     {
311         if (instance != null)
312             return instance.globalCookies;
313         else
314             return null;
315     }
316 
317     /***
318      * Adds a cookie to the globalCookies
319      * 
320      * @param cookieName
321      * @param numberToAdd
322      */
323     public static void addToGlobalCookie(String cookieName, int numberToAdd)
324     {
325         if (instance == null)
326             return;
327 
328         Integer integer = (Integer) instance.globalCookies.get(cookieName);
329         if (integer == null)
330             instance.globalCookies.put(cookieName, new Integer(numberToAdd));
331         else
332             instance.globalCookies.put(cookieName, new Integer(integer.intValue() + numberToAdd));
333 
334         ((ExpFrame) Application.getApplicationFrame()).checkEnabled();
335     }
336 
337     /***
338      * Adds a cookie to the globalCookies
339      * 
340      * @param cookieName
341      * @param numberToAdd
342      */
343     public static void ensureGlobalCookie(String cookieName, int numberToEnsure)
344     {
345         if (instance == null)
346             return;
347 
348         instance.globalCookies.put(cookieName, new Integer(numberToEnsure));
349 
350         if (Application.getApplicationFrame() != null)
351            ((ExpFrame) Application.getApplicationFrame()).checkEnabled();
352     }
353 
354     /***
355      * Removes the specified number of ticks from this cookie in the
356      * globalCookies
357      * 
358      * @param cookieName
359      * @param numberToRemove
360      */
361     public static void removeFromGlobalCookie(String cookieName, int numberToRemove)
362     {
363         if (instance == null)
364             return;
365 
366         Integer integer = (Integer) instance.globalCookies.get(cookieName);
367         if (integer == null)
368             instance.globalCookies.put(cookieName, new Integer(0));
369         else
370         {
371             int result = integer.intValue() - numberToRemove;
372             result = (result < 0 ? 0 : result);
373             instance.globalCookies.put(cookieName, new Integer(result));
374         }
375 
376         ((ExpFrame) Application.getApplicationFrame()).checkEnabled();
377     }
378 
379     /***
380      * Adds a cookie to the localCookies for the given Reference
381      * 
382      * @param cookieName
383      * @param numberToAdd
384      * @param reference this is thelocal reference (usually the tool/applet
385      *        itself)
386      */
387     public static void addToLocalCookie(String cookieName, int numberToAdd, Object reference)
388     {
389         if (instance == null)
390             return;
391 
392         Map localCookiesForReference = (Map) instance.localCookies.get(reference);
393         if (localCookiesForReference == null)
394         {
395             localCookiesForReference = new HashMap();
396             instance.localCookies.put(reference, localCookiesForReference);
397             localCookiesForReference.put(cookieName, new Integer(numberToAdd));
398         }
399         else
400         {
401             Integer integer = (Integer) localCookiesForReference.get(cookieName);
402             if (integer == null)
403                 localCookiesForReference.put(cookieName, new Integer(numberToAdd));
404             else
405                 localCookiesForReference.put(cookieName, new Integer(integer.intValue() + numberToAdd));
406         }
407 
408         ((ExpFrame) Application.getApplicationFrame()).checkEnabled();
409     }
410 
411     /***
412      * Adds a cookie to the localCookies for the given Reference
413      * 
414      * @param cookieName
415      * @param numberToEnsure
416      * @param reference this is thelocal reference (usually the tool/applet
417      *        itself)
418      */
419     public static void ensureLocalCookie(String cookieName, int numberToEnsure, Object reference)
420     {
421         if (instance == null)
422             return;
423 
424         Map localCookiesForReference = (Map) instance.localCookies.get(reference);
425         if (localCookiesForReference == null)
426         {
427             localCookiesForReference = new HashMap();
428             instance.localCookies.put(reference, localCookiesForReference);
429         }
430 
431         localCookiesForReference.put(cookieName, new Integer(numberToEnsure));
432 
433         ((ExpFrame) Application.getApplicationFrame()).checkEnabled();
434     }
435 
436     /***
437      * Removes the specified number of ticks from this cookie in the
438      * localCookies for the given Reference
439      * 
440      * @param cookieName
441      * @param numberToRemove
442      * @param reference this is thelocal reference (usually the tool/applet
443      *        itself)
444      */
445     public static void removeFromLocalCookie(String cookieName, int numberToRemove, Object reference)
446     {
447         if (instance == null)
448             return;
449 
450         Map localCookiesForReference = (Map) instance.localCookies.get(reference);
451         if (localCookiesForReference != null)
452         {
453             Integer integer = (Integer) localCookiesForReference.get(cookieName);
454             if (integer == null)
455                 localCookiesForReference.put(cookieName, new Integer(0));
456             else
457             {
458                 int result = integer.intValue() - numberToRemove;
459                 result = (result < 0 ? 0 : result);
460                 localCookiesForReference.put(cookieName, new Integer(result));
461             }
462         }
463 
464         ((ExpFrame) Application.getApplicationFrame()).checkEnabled();
465     }
466 
467     /***
468      * @return Map cookies
469      */
470     public static Map getLocalCookies()
471     {
472         ExpInternalFrame frame = ((ExpFrame) getApplicationFrame()).getActiveFrame();
473         if (frame != null)
474         {
475             Object reference = frame.getApplet();
476             if (reference != null)
477                 return (Map) instance.localCookies.get(reference);
478         }
479 
480         return null;
481     }
482 
483     /***
484      * @return Returns the currently active reference if there is one
485      */
486     protected static Object getLocalReference()
487     {
488         if (getApplicationFrame() == null)
489             return localReference;
490 
491         ExpInternalFrame frame = ((ExpFrame) getApplicationFrame()).getActiveFrame();
492         if (frame != null)
493         {
494             return frame.getApplet();
495         }
496 
497         return null;
498     }
499 
500     protected static void cleanUpForReference(Object reference)
501     {
502         if (instance != null)
503         {
504             instance.localCookies.remove(reference);
505             instance.activeComponents.remove(reference);
506 
507             ArrayList componentList = (ArrayList) instance.componentTracker.get(reference);
508             if (componentList != null)
509             {
510                 for (int i = 0; i < componentList.size(); i++)
511                 {
512                     instance.componentCookies.remove(componentList.get(i));
513                 }
514                 instance.componentTracker.remove(reference);
515             }
516 
517             if (instance.frame != null)
518                 instance.frame.getListener().cleanUpForReference(reference);
519         }
520     }
521 
522     /***
523      * A component group is a group of components within a frame. Each of the
524      * components in the group will have different enablements in terms of menus
525      * etc.
526      * 
527      * At anytime it is possible to change which component is active in the
528      * group. A component belongs to a local tool
529      *  
530      */
531     public static void setActiveComponent(Object localReference, Object component)
532     {
533         if (instance == null)
534             return;
535 
536         instance.activeComponents.put(localReference, component);
537         ((ExpFrame) getApplicationFrame()).checkEnabled();
538         log.debug("Active component set: Reference-" + localReference + ", Component-" + component);
539     }
540 
541     public static void unsetActiveComponent()
542     {
543         if (instance == null)
544             return;
545 
546         Object reference = getLocalReference();
547         if (reference != null)
548         {
549             instance.activeComponents.remove(reference);
550             log.debug("Active component unset: Reference-" + reference);
551         }
552         ((ExpFrame) getApplicationFrame()).checkEnabled();
553     }
554 
555     public static Map getActiveComponentCookies()
556     {
557         if (instance == null)
558             return null;
559 
560         Object reference = getLocalReference();
561         if (reference != null)
562         {
563             Object activeComponent = instance.activeComponents.get(reference);
564             if (activeComponent != null)
565                 return (Map) instance.componentCookies.get(activeComponent);
566         }
567 
568         return null;
569     }
570 
571     public static Object getActiveComponent()
572     {
573         if (instance == null)
574             return null;
575 
576         Object reference = getLocalReference();
577         if (reference != null)
578             return instance.activeComponents.get(reference);
579 
580         return null;
581     }
582 
583     /***
584      * Adds a cookie to the localCookies for the given Reference
585      * 
586      * @param cookieName
587      * @param numberToEnsure
588      * @param reference this is the component
589      */
590     public static void ensureComponentCookie(String cookieName, int numberToEnsure, Object localReference, Object component)
591     {
592         if (instance == null)
593             return;
594 
595         Map cookiesForThisComponent = (Map) instance.componentCookies.get(component);
596         if (cookiesForThisComponent == null)
597         {
598             cookiesForThisComponent = new HashMap();
599             instance.componentCookies.put(component, cookiesForThisComponent);
600 
601             //This little bit of code is so that we can keep track of alll
602             // of the components for each local reference so that we can delete
603             // them
604             // when thelocal reference is deleted
605             ArrayList componentsList = (ArrayList) instance.componentTracker.get(localReference);
606             if (componentsList == null)
607             {
608                 componentsList = new ArrayList();
609                 instance.componentTracker.put(localReference, componentsList);
610             }
611             if (!componentsList.contains(component))
612                 componentsList.add(component);
613         }
614 
615         cookiesForThisComponent.put(cookieName, new Integer(numberToEnsure));
616 
617         if (Application.getApplicationFrame() != null)
618             ((ExpFrame) Application.getApplicationFrame()).checkEnabled();
619     }
620     
621     /***
622      * Returns the IconImage currently beingusedby thisapplication for Frames
623      * etc
624      * 
625      * @return
626      */
627     public static String getIconImage()
628     {
629         if (instance == null)
630             return null;
631 
632         String iconImage = properties.getProperty(ExpConstants.EXPF_APP_FRAME_ICON_IMAGE);
633         if (iconImage == null)
634             iconImage = ExpConstants.DEFAULT_WINDOW_ICON;
635         return iconImage;
636     }
637 
638     /***
639      * Returns the application splash image
640      * 
641      * @return splashScreenImage
642      */
643     public static String getSplashImage()
644     {
645         String splashScreenImage = properties.getProperty(ExpConstants.EXPF_APP_SPLASHSCREEN_IMAGE);
646         if (splashScreenImage == null)
647             splashScreenImage = ExpConstants.DEFAULT_SPLASH_SCREEN_IMAGE;
648         return splashScreenImage;
649     }
650 
651     /***
652      * Returns the application splash image
653      * 
654      * @return splashScreenImage
655      */
656     public static String getAboutImage()
657     {
658         String aboutImage = properties.getProperty(ExpConstants.EXPF_APP_ABOUT_IMAGE);
659         if (aboutImage == null)
660             aboutImage = ExpConstants.DEFAULT_SPLASH_SCREEN_IMAGE;
661         return aboutImage;
662     }
663 
664     /***
665      * constructs a set of properties belinging to each module
666      * 
667      * @param properties
668      * @return
669      */
670     protected Map constructModulePropertiesMap(Properties properties)
671     {
672         Map propertiesMap = new HashMap();
673         StringTokenizer modulesTokenizer = new StringTokenizer(properties.getProperty(ExpConstants.EXPF_APP_MODULES), ",");
674         while (modulesTokenizer.hasMoreTokens())
675         {
676             String name = modulesTokenizer.nextToken();
677             Properties moduleProperties = PropertiesUtils.subset(name + ".", properties);
678 
679             String moduleManagerClassName = moduleProperties.getProperty(ExpConstants.EXPF_MODULE_MANAGER);
680             if (moduleManagerClassName != null)
681             {
682                 propertiesMap.put(moduleManagerClassName, moduleProperties);
683             }
684         }
685         return propertiesMap;
686     }
687     
688     /***
689      * This returns a map of the properties specified for the module 
690      * with the class name provided
691      * @param moduleClassName
692      * @return
693      */
694     public Properties getPropertiesForModule(String moduleClassName)
695     {
696     	return (Properties) propertiesMap.get(moduleClassName);
697     }
698     
699 
700     /***
701      * This method initialises the modules
702      */
703     private void initialiseModules() throws Exception
704     {
705         /* Open up all of the moduleSpecific code */
706         splashScreen.updateText("Initialising modules...");
707         ArrayList modules = getModuleManagerClassNames(properties);
708         propertiesMap = constructModulePropertiesMap(properties);
709 
710         for (int i = 0; i < modules.size(); i++)
711         {
712             Object reference = null;
713             try
714             {
715                 String moduleClassName = ((String) modules.get(i));
716                 log.debug("Attempting to load class '" + moduleClassName + "' as a module manager.");
717 
718                 Class moduleDescriptorClass = Class.forName(moduleClassName);
719                 ExpModuleManager moduleManager = (ExpModuleManager) moduleDescriptorClass.newInstance();
720                 reference = moduleManager;
721 
722                 log.info("Initialising module " + moduleManager.getName() + " version " + moduleManager.getVersion());
723                 splashScreen.updateText("Initialising " + moduleManager.getName() + " Version " + moduleManager.getVersion()); //$NON-NLS-2$
724 
725                 long one = (new Date()).getTime();
726                 moduleManager.initialiseCore(getPropertiesForModule(moduleClassName));
727                 long two = (new Date()).getTime();
728                 moduleManager.initialiseGui();
729                 long three = (new Date()).getTime();
730 
731                 frame.getListener().addGlobalActionListener(moduleManager.getGlobalListener(), moduleManager);
732                 modulesVector.addElement(moduleManager);
733                 modulesHash.put(moduleManager.getName(), moduleManager);
734 
735                 long four = (new Date()).getTime();
736 
737                 log.debug("Initialise core: " + (two - one) + " milliseconds");
738                 log.debug("Initialise gui: " + (three - two) + " milliseconds");
739                 log.debug("The rest: " + (four - three) + " milliseconds");
740             }
741             catch (Exception e)
742             {
743                 com.explosion.utilities.exception.ExceptionManagerFactory.getExceptionManager().manageException(e, "Exception caught while initialising module " + (String) modules.get(i) + "'.");
744                 if (reference != null)
745                 {
746                     //Make sure there are no references left to this
747                     // moduleManager
748                     frame.getListener().removeGlobalActionListenersForReference(reference);
749                     modulesVector.remove(reference);
750                     if (modulesHash.containsValue(reference))
751                     {
752                         Iterator it = modulesHash.keySet().iterator();
753                         while (it.hasNext())
754                         {
755                             Object key = it.next();
756                             if (modulesHash.get(key) == reference)
757                             {
758                                 modulesHash.remove(key);
759                                 break;
760                             }
761                         }
762                     }
763                 }
764             }
765         }
766     }
767     
768     /***
769      * This method parses all of the manifest entries for module manager entries
770      */
771     public static ArrayList getModuleManagerClassNames(Properties properties) throws Exception
772     {
773         ArrayList classNames = new ArrayList();
774         ArrayList temp = new ArrayList();
775         StringTokenizer modulesTokenizer = new StringTokenizer(properties.getProperty(ExpConstants.EXPF_APP_MODULES), ",");
776         while (modulesTokenizer.hasMoreTokens())
777         {
778             String name = modulesTokenizer.nextToken();
779             Properties moduleProperties = PropertiesUtils.subset(name + ".", properties);
780             String moduleManagerClassName = moduleProperties.getProperty(ExpConstants.EXPF_MODULE_MANAGER);
781             if (moduleManagerClassName == null)
782             {
783                 log.debug("Found module manifest entry with no module manager class name specified. This entry will be ignored. ");
784                 continue;
785             }
786 
787             if (!moduleManagerClassName.trim().equals(moduleManagerClassName))
788                 throw new ModuleLoadException("Invalid class name, contains whitespace. '" + moduleManagerClassName + "'.");
789 
790             String loadOrderString = moduleProperties.getProperty(ExpConstants.EXPF_MODULE_LOAD_ORDER);
791             int loadOrder = -1;
792             if (loadOrderString == null)
793             {
794                 log.debug("Found module manifest entry with no load order specified. This entry will be ignored.");
795                 continue;
796             }
797             
798             try
799             {
800                 loadOrder = Integer.parseInt(loadOrderString) - 1;
801                 log.debug("Load order " + loadOrder);
802             }
803             catch (NumberFormatException ex)
804             {
805                 log.debug("Found module manifest entry with an invalid load order specified. This entry will be ignored. The value provided was " + loadOrderString + "   this is not a number.");
806             }
807             
808             /* I should probably make a comparator but this works so ... whatever (its late) */
809             String sortString = "";
810             for (int i=0;i<loadOrder;i++)
811             {
812                 sortString += "=";
813             }
814             log.debug(sortString + "|" + moduleManagerClassName);
815             temp.add(sortString + "|" + moduleManagerClassName);
816         }
817 
818         Collections.sort(temp);
819         for (int i = temp.size()-1; i >= 0; i--)
820         {
821             String a = (String) temp.get(i);
822             log.debug(a);
823             classNames.add(a.substring(a.indexOf("|") + 1));
824         }
825 
826         return classNames;
827     }    
828 
829     public void applyPreferences()
830     {
831         try
832         {
833             /* Apply the system preferences */
834             SystemPreferences.applyPreferences();
835 
836             ((ExpFrame) Application.getApplicationFrame()).getListener().updateLookAndFeelOfHelp();
837 
838             /***
839              * re-initialise logging
840              */
841             initialiseLogging();
842             
843             /*
844              * Iterate through all of the currently active module references and
845              * apply their preferences
846              */
847             Iterator iterator = localCookies.keySet().iterator();
848             while (iterator.hasNext())
849             {
850                 Object component = iterator.next();
851                 if (component instanceof ExpComponent)
852                     ((ExpComponent) component).applyPreferences();
853             }
854             
855             /* Iterate trough the list of windows to apply preferences there if need be */
856             JInternalFrame frames[] = ((ExpFrame)Application.getApplicationFrame()).getAllInternalFrames();
857             for (int i=0;i<frames.length;i++)
858             {
859                 Object component = ((ExpInternalFrame) frames[i]).getApplet();
860                 if (component instanceof ExpComponent)
861                     ((ExpComponent) component).applyPreferences();
862             }
863         }
864         catch (Exception e)
865         {
866             com.explosion.utilities.exception.ExceptionManagerFactory.getExceptionManager().manageException(e, "Exception caught while saving properties ");
867         }
868     }
869 
870     /***
871      * Writes the application properties out to file if property
872      * SAVESETTINGSONEXIT is set to true or is not present Also saves LASTDIR
873      */
874     public void savePreferences()
875     {
876         try
877         {
878             SystemPreferences.getPreference(ExpConstants.LASTDIR).setValue(System.getProperty("user.dir"));
879 
880             /* Save system preferences */
881             savePreferences(SystemPreferences.getPreferences());
882 
883             /* Save module preferences */
884             for (int i = 0; i < modulesVector.size(); i++)
885                 savePreferences(((ExpModuleManager) modulesVector.elementAt(i)).getPreferences());
886         }
887         catch (Exception e)
888         {
889             com.explosion.utilities.exception.ExceptionManagerFactory.getExceptionManager().manageException(e, "Exception caught while saving properties.  It is likely that they have not been properly saved.");
890         }
891     }
892 
893     /* Little loop util */
894     private void savePreferences(Vector preferences) throws Exception
895     {
896         if (preferences != null)
897         {
898             for (int i = 0; i < preferences.size(); i++)
899                 ((Preference) preferences.elementAt(i)).save();
900         }
901     }
902 
903     public static JFrame getApplicationFrame()
904     {
905         if (instance == null)
906             return null;
907 
908         return instance.frame;
909     }
910 
911     public void exit()
912     {
913         if (frame.closeAllFrames())
914         {
915             boolean saveOnExit = ((Boolean) SystemPreferences.getPreference(ExpConstants.SAVESETTINGSONEXIT).getValue()).booleanValue();
916             if (saveOnExit)
917                 savePreferences();
918 
919             isAlive = false;
920             frame.dispose();
921             frame = null;
922             System.exit(0);
923         }
924     }
925     
926     /***
927      * For the sake of automoated GUI testing only.  Not really usefull for anything else.  Assume that 
928      * if you can see it, it is alive.
929      * @return Returns the isAlive.
930      */
931     public boolean isAlive()
932     {
933         return isAlive;
934     }
935     
936     /***
937      * @deprecated use getPreferences() instead
938      * @return Properties
939      */
940     public Properties getProperties()
941     {
942         return new Properties();
943     }
944 
945     public static void initialiseLogging()
946     {
947         try
948         {
949             /* Reset the logmanager configuration */
950             LogManager.resetConfiguration();
951 
952             /* Make some decisions */
953             boolean logToConsole = ((Boolean) SystemPreferences.getPreference(ExpConstants.LOG_TO_CONSOLE).getValue()).booleanValue();
954             boolean logToFile = ((Boolean) SystemPreferences.getPreference(ExpConstants.LOG_TO_FILE).getValue()).booleanValue();
955 
956             /* Resolve some handy locals */
957             String rootLogLevel = (String) SystemPreferences.getPreference(ExpConstants.ROOT_LOG_LEVEL).getValue();
958             String patternString = (String) SystemPreferences.getPreference(ExpConstants.LOG_PATTERN).getValue();
959             String customLogLevel = (String) SystemPreferences.getPreference(ExpConstants.CUSTOM_LOG_LEVEL).getValue();
960             PatternLayout layout = new PatternLayout(patternString);
961 
962             /* Set root log level */
963             LogManager.getRootLogger().setLevel(Level.toLevel(rootLogLevel));
964 
965             /* Create the appenders */
966             RollingFileAppender rollingFileAppender = null;
967             ConsoleAppender consoleAppender = null;
968 
969             /* Console logging */
970             if (logToConsole)
971             {
972                 consoleAppender = new org.apache.log4j.ConsoleAppender(layout);
973                 LogManager.getRootLogger().addAppender(consoleAppender);
974             }
975 
976             /* File logging */
977             if (logToFile)
978             {
979                 File logFile = (File) SystemPreferences.getPreference(ExpConstants.LOG_FILE).getValue();
980                 if (logFile.getParentFile() == null || !logFile.getParentFile().exists() || logFile.isDirectory())
981                 {
982                     JOptionPane.showMessageDialog(Application.getApplicationFrame(), "Unable to find log file " + logFile.getAbsolutePath() + "  as it is not a valid location. Default location  "
983                             + (File) SystemPreferences.getPreference(ExpConstants.LOG_FILE).getDefaultValue()
984                             + "  will be used instead.  Please check your application properties to ensure you have specified a valid location. ", "Error !", JOptionPane.ERROR_MESSAGE);
985                     logFile = (File) SystemPreferences.getPreference(ExpConstants.LOG_FILE).getDefaultValue();
986                 }
987 
988                 rollingFileAppender = new RollingFileAppender(layout, logFile.getAbsolutePath());
989                 LogManager.getRootLogger().addAppender(rollingFileAppender);
990             }
991 
992             /* Custom logging */
993             List customValues = SystemPreferences.getPreference(ExpConstants.CUSTOM_LOG_VALUES).getValues();
994             for (Iterator it = customValues.iterator(); it.hasNext();)
995             {
996                 String customValue = (String) it.next();
997                 String tmpVal = null;
998                 String tmpLvl = customLogLevel;
999                 int index = customValue.indexOf("=");
1000                 if (index < 0)
1001                 {
1002                     tmpVal = customValue;
1003                 }
1004                 else
1005                 {
1006                     tmpVal = customValue.substring(0, index);
1007                     tmpLvl = customValue.substring(index + 1, customValue.length());
1008                 }
1009 
1010                 Logger logger = LogManager.getLogger(tmpVal);
1011                 logger.setLevel(Level.toLevel(tmpLvl));
1012                 logger.setAdditivity(false);
1013                 
1014                 if (logToFile)
1015                     logger.addAppender(rollingFileAppender);
1016                 
1017                 if (logToConsole)
1018                     logger.addAppender(consoleAppender);
1019             }
1020 
1021         }
1022         catch (HeadlessException e)
1023         {
1024             ExceptionManagerFactory.getExceptionManager().manageException(e, "Exception caught while initialising logging.");
1025         }
1026         catch (IOException e)
1027         {
1028             ExceptionManagerFactory.getExceptionManager().manageException(e, "Exception caught while initialising logging");
1029         }
1030     }
1031 
1032     /***
1033      * This updates the look and feel
1034      */
1035     public void updateLookAndFeel(Component component)
1036     {
1037         updateLookAndFeel((String) SystemPreferences.getPreference(ExpConstants.LAF).getValue(), component);
1038     }
1039 
1040     /***
1041      * This updates the look and feel
1042      */
1043     public void updateLookAndFeel()
1044     {
1045         updateLookAndFeel((String) SystemPreferences.getPreference(ExpConstants.LAF).getValue(), getApplicationFrame());
1046     }
1047 
1048     /***
1049      * This updates the look and feel
1050      */
1051     private void updateLookAndFeel(String currentLookAndFeel, Component component)
1052     {
1053         try
1054         {
1055             UIManager.setLookAndFeel(currentLookAndFeel);
1056             if (component != null)
1057             {
1058                 SwingUtilities.updateComponentTreeUI(component);
1059             }
1060 
1061             for (Iterator it = ExpConstants.looksList.iterator(); it.hasNext();)
1062             {
1063                 ExpLookAndFeel lf = (ExpLookAndFeel) ExpConstants.looksMap.get(it.next());
1064                 if (UIManager.getLookAndFeel().getClass().getName().equals(lf.getClassName()))
1065                 {
1066                     Application.ensureGlobalCookie(lf.getActionName(),0);
1067                 }
1068                 else
1069                 {
1070                     Application.ensureGlobalCookie(lf.getActionName(),1);
1071                 }
1072             }
1073         }
1074         catch (Exception ex)
1075         {
1076             com.explosion.utilities.exception.ExceptionManagerFactory.getExceptionManager().manageException(ex, "Exception caught while updating look and feel");
1077         }
1078     }
1079 
1080     /***
1081      * Method getHelpBroker.returns the halpBroker for this application
1082      * 
1083      * @return HelpBroker
1084      */
1085     public static HelpBroker getHelpBroker() throws Exception
1086     {
1087         if (instance == null)
1088             return null;
1089 
1090         if (instance.helpSet == null)
1091         {
1092             String path = (String) SystemPreferences.getPreference(ExpConstants.HELP_FILE_NAME).getValue();
1093             //URL helpsetFile =
1094             // instance.getClass().getClassLoader().getResource(path);
1095             URL url = HelpSet.findHelpSet(instance.getClass().getClassLoader(), path);
1096             
1097             log.debug(url);
1098             //URLConnection conn = url.openStream();
1099             log.debug((String) SystemPreferences.getPreference(ExpConstants.HELP_FILE_NAME).getValue());
1100             instance.helpSet = new HelpSet(instance.getClass().getClassLoader(), url);
1101             instance.helpBroker = instance.helpSet.createHelpBroker();
1102         }
1103 
1104         return instance.helpBroker;
1105 
1106     }
1107 
1108     /***
1109      * Returns the menuMap.
1110      * 
1111      * @return Vector
1112      */
1113     public static Vector getMenuMap()
1114     {
1115         return menuMap;
1116     }
1117 
1118     //
1119     //
1120     //
1121     //   THESE METHODS AND VARIABLES ARE USED DURING TESTING ONLY
1122     // 
1123     //
1124     //  
1125 
1126     private static Object localReference = null;
1127 
1128     /***
1129      * This methos is used for testing
1130      */
1131     protected void setLocalReference(Object object)
1132     {
1133         localReference = object;
1134     }
1135 
1136 }