Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/gui4j/core/impl/Gui4jImpl.java


1   package org.gui4j.core.impl;
2   
3   import java.io.File;
4   import java.io.IOException;
5   import java.io.ObjectInputStream;
6   import java.io.ObjectOutputStream;
7   import java.io.Serializable;
8   import java.lang.reflect.InvocationTargetException;
9   import java.lang.reflect.UndeclaredThrowableException;
10  import java.net.URL;
11  import java.util.HashSet;
12  import java.util.Set;
13  
14  import org.apache.commons.logging.Log;
15  import org.apache.commons.logging.LogFactory;
16  import org.gui4j.Gui4jCallBase;
17  import org.gui4j.Gui4jController;
18  import org.gui4j.Gui4jDialog;
19  import org.gui4j.Gui4jValidator;
20  import org.gui4j.Gui4jView;
21  import org.gui4j.Gui4jWindow;
22  import org.gui4j.core.Gui4jCallFactory;
23  import org.gui4j.core.Gui4jComponentContainer;
24  import org.gui4j.core.Gui4jComponentContainerManager;
25  import org.gui4j.core.Gui4jComponentManager;
26  import org.gui4j.core.Gui4jInternal;
27  import org.gui4j.core.Gui4jReflectionManager;
28  import org.gui4j.core.Gui4jThreadManager;
29  import org.gui4j.core.call.Gui4jCallParser;
30  import org.gui4j.core.interfaces.Gui4jWindowInternal;
31  import org.gui4j.core.util.MethodCall;
32  import org.gui4j.event.SimpleEvent;
33  import org.gui4j.exception.Gui4jDefaultErrorHandler;
34  import org.gui4j.exception.Gui4jErrorHandler;
35  import org.gui4j.exception.Gui4jException;
36  import org.gui4j.exception.Gui4jExceptionHandler;
37  
38  
39  /**
40   * This is the base initialization class of Gui4j. An instance of
41   * Gui4j holds all other necessary instances to deal with 
42   * graphical user interfaces with gui4j. Note that it is possible
43   * to use different instances of Gui4j, but each instance has its
44   * own workspace and they are completely independant; and each
45   * instance maintains its own cache for reflection calls and
46   * worker threads.
47   */
48  final class Gui4jImpl implements Serializable, Gui4jInternal
49  {
50      private Log mLogger = LogFactory.getLog(getClass());
51      private final Gui4jComponentManager mGui4jComponentManager;
52      private final Gui4jComponentContainerManager mGui4jComponentContainerManager;
53      private final Gui4jReflectionManager mGui4jReflectionManager;
54      private final Gui4jThreadManager mGui4jThreadManager;
55      private final SimpleEvent eViewCollection = new SimpleEvent();
56      private boolean mValidateXML;
57      private boolean mLogInvoke;
58      private boolean mTraceWorkerInvocation = false;
59      private Gui4jErrorHandler mErrorHandler;
60  
61      private Set windowCollector = new HashSet();
62  
63      public Gui4jImpl(boolean validateXML, boolean logInvoke, int numberOfWorkerThreads, URL configURL)
64      {
65          mValidateXML = validateXML;
66          mLogInvoke = logInvoke;
67          mGui4jComponentManager = Gui4jComponentManager.getNewInstance(this);
68          mGui4jComponentContainerManager = Gui4jComponentContainerManager.getNewInstance(this);
69          mGui4jReflectionManager = Gui4jReflectionManager.getNewInstance();
70          mGui4jThreadManager = Gui4jThreadManager.getNewInstance(this, numberOfWorkerThreads);
71          configure(configURL);
72      }
73  
74      /**
75       * @return the contained <code>Gui4jComponentManager</code>
76       */
77      public Gui4jComponentManager getGui4jComponentManager()
78      {
79          return mGui4jComponentManager;
80      }
81  
82      /**
83       * @return the contained <code>Gui4jComponentContainerManager</code>
84       */
85      public Gui4jComponentContainerManager getGui4jComponentContainerManager()
86      {
87          return mGui4jComponentContainerManager;
88      }
89  
90      /**
91       * @return the contained <code>Gui4jReflectionManager</code>
92       */
93      public Gui4jReflectionManager getGui4jReflectionManager()
94      {
95          return mGui4jReflectionManager;
96      }
97  
98      /**
99       * @return the used <code>Gui4jThreadManager</code>
100      */
101     public Gui4jThreadManager getGui4jThreadManager()
102     {
103         return mGui4jThreadManager;
104     }
105 
106     /**
107      * @param configurationSource the URL of the XML configuration file for the
108      * <code>Gui4jComponents</code> to be installed
109      */
110     private void configure(URL configurationSource)
111     {
112         assert configurationSource != null;
113         mGui4jComponentManager.configure(configurationSource);
114     }
115 
116     /**
117      * Is called after the setter of an edit field returns without raising an
118      * exception. If the given Controller (Gui4jCallBase) implements a suitable
119      * method, that method is called, otherwise, nothing happens.
120      * @param gui4jCallBase
121      * @param context
122      */
123     public void handleSuccess(Gui4jCallBase gui4jCallBase, Object context)
124     {
125         if (context == null)
126         {
127             return;
128         }
129 
130         try
131         {
132             Gui4jExceptionHandler exceptionHandler =
133                 gui4jCallBase != null ? gui4jCallBase.getExceptionHandler() : null;
134             Gui4jExceptionHandler oldHandler = null;
135             while (exceptionHandler != null && exceptionHandler != oldHandler)
136             {
137                 oldHandler = exceptionHandler;
138                 MethodCall call =
139                     getGui4jReflectionManager().getMethod(
140                         "errorHandling",
141                         exceptionHandler.getClass(),
142                         "handleSuccess",
143                         new Class[] { context.getClass()},
144                         false);
145                 if (call != null)
146                 {
147                     call.invoke(exceptionHandler, new Object[] { context });
148                     break;
149                 }
150                 exceptionHandler = exceptionHandler.getDelegationExceptionHandler();
151             }
152         }
153         catch (Throwable tHandler)
154         {
155             internalError(tHandler);
156         }
157     }
158 
159     private Throwable unpack(Throwable t)
160     {
161         while (t != null)
162         {
163             if (t.getCause() != null && t instanceof UndeclaredThrowableException)
164             {
165                 t = t.getCause();
166                 continue;
167             }
168             if (t instanceof InvocationTargetException)
169             {
170                 t = ((InvocationTargetException) t).getTargetException();
171                 continue;
172             }
173             break;
174         }
175         return t;
176     }
177 
178     /**
179      * Is called for all exceptions occuring during execution of methods. If the
180      * given Controller (Gui4jCallBase) defines a suitable error handler, that
181      * error handler is called. Otherwise an internal error is raisen.
182      * @param gui4jCallBase
183      * @param t
184      * @param context
185      */
186     public void handleException(Gui4jCallBase gui4jCallBase, Throwable t, Object context)
187     {
188         assert t != null;
189         t = unpack(t);
190         boolean handled = false;
191         Gui4jExceptionHandler topExceptionHandler =
192             gui4jCallBase != null ? gui4jCallBase.getExceptionHandler() : null;
193         try
194         {
195             Gui4jExceptionHandler exceptionHandler = topExceptionHandler;
196             Gui4jExceptionHandler oldHandler = null;
197             if (context != null)
198             {
199                 while (!handled && exceptionHandler != null && oldHandler != exceptionHandler)
200                 {
201                     oldHandler = exceptionHandler;
202                     MethodCall call =
203                         getGui4jReflectionManager().getMethod(
204                             "errorHandling",
205                             exceptionHandler.getClass(),
206                             "handleException",
207                             new Class[] { context.getClass(), t.getClass()},
208                             false);
209                     if (call != null)
210                     {
211                         handled = true;
212                         call.invoke(exceptionHandler, new Object[] { context, t });
213                     }
214                     exceptionHandler = exceptionHandler.getDelegationExceptionHandler();
215                 }
216             }
217             exceptionHandler = topExceptionHandler;
218             oldHandler = null;
219             while (!handled && exceptionHandler != null && oldHandler != exceptionHandler)
220             {
221                 oldHandler = exceptionHandler;
222                 MethodCall call =
223                     getGui4jReflectionManager().getMethod(
224                         "errorHandling",
225                         exceptionHandler.getClass(),
226                         "handleException",
227                         new Class[] { t.getClass()},
228                         false);
229                 if (call != null)
230                 {
231                     handled = true;
232                     call.invoke(exceptionHandler, new Object[] { t });
233                 }
234             }
235         }
236         catch (Throwable tExceptionHandler)
237         {
238             handled = true;
239             internalError(tExceptionHandler);
240         }
241         if (!handled)
242         {
243             internalError(t);
244         }
245     }
246 
247     private void internalError(Throwable t)
248     {
249         mLogger.error("Internal error", t);
250         if (Thread.currentThread() instanceof Gui4jThreadManager.WorkerThread)
251         {
252             Gui4jThreadManager.WorkerThread wt = (Gui4jThreadManager.WorkerThread) Thread.currentThread();
253             if (wt.getCallStack() != null)
254             {
255                 mLogger.error("Invoker of thread [" + wt.getName() + "] was:", wt.getCallStack());
256             }
257         }
258         try
259         {
260             if (mErrorHandler != null)
261             {
262                 mErrorHandler.internalError(t);
263             }
264             else
265             {
266                 Gui4jDefaultErrorHandler.getInstance().internalError(t);
267             }
268         }
269         catch (Throwable tError)
270         {
271             mLogger.error("Error occured while handling internal error", tError);
272         }
273     }
274 
275     /**
276      * Loads the specified resource file in the cache. The method can be used to
277      * ensure that some XML resource files are loaded before serializing the
278      * current state.
279      * @param controllerClass the controller for the given resource file
280      * @param resourceName the name of the xml resource to load
281      */
282     public void readResourceFile(Class controllerClass, String resourceName)
283     {
284         String fullyQuantifiedName =
285             Gui4jComponentContainerManager.getResourceNameFullyQuantified(
286                 Gui4jComponentContainerManager.getBaseName(controllerClass),
287                 resourceName);
288 
289         URL cfg = controllerClass.getResource(resourceName);
290         Gui4jComponentContainer gui4jComponentContainer =
291             mGui4jComponentContainerManager.getGui4jComponentContainer(controllerClass, fullyQuantifiedName, cfg);
292 
293         if (gui4jComponentContainer.isDefined("TOP"))
294         {
295             gui4jComponentContainer.getGui4jQualifiedComponent("TOP");
296         }
297         if (gui4jComponentContainer.isDefined("MENU"))
298         {
299             gui4jComponentContainer.getGui4jQualifiedComponent("MENU");
300         }
301     }
302 
303     private void writeObject(ObjectOutputStream out) throws IOException
304     {
305         mLogger = null;
306         out.defaultWriteObject();
307     }
308 
309     private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
310     {
311         in.defaultReadObject();
312         mLogger = LogFactory.getLog(getClass());
313     }
314 
315     /**
316      * @return true if XML files should be validated
317      */
318     public boolean validateXML()
319     {
320         return mValidateXML;
321     }
322 
323     /**
324      * @return true if invocation calls should be logged
325      */
326     public boolean logInvoke()
327     {
328         return mLogInvoke;
329     }
330 
331     /**
332      * @return true if the call stack of invokers of a WorkerThread
333      * should be saved and then printed in case of an internal error.
334      */
335     public boolean traceWorkerInvocation()
336     {
337         return mTraceWorkerInvocation;
338     }
339 
340     /**
341      * Defines if the call stack of invokers of WorkerThreads should
342      * always be saved so that it can be printed together with the
343      * thread's own stack trace in case of an internal error.<br>
344      * This feature is recommended only for debugging
345      * purposes since the negative performance impact of creating a
346      * call stack (i.e. instance of Throwable) for each invocation of a
347      * WorkerThread has not been measured.
348      * @param b true, to turn the feature on, false to turn it off
349      */
350     public void setTraceWorkerInvocation(boolean b)
351     {
352         mTraceWorkerInvocation = b;
353     }
354 
355     /**
356      * @return true if special debug messages should be written. This 
357      * method should be removed at some stage.
358      */
359     public boolean traceMode()
360     {
361         return false;
362     }
363 
364     /**
365      * Sets the errorHandler.
366      * @param errorHandler The errorHandler to set
367      */
368     public void setErrorHandler(Gui4jErrorHandler errorHandler)
369     {
370         mErrorHandler = errorHandler;
371     }
372 
373     /**
374      * Returns the viewCollector.
375      * @return Set
376      */
377     public Set getViewCollector()
378     {
379         return windowCollector;
380     }
381 
382     public void addToWindowCollector(Gui4jWindowInternal window)
383     {
384         mLogger.debug("Adding window to list. Current length (before adding is): " + windowCollector.size());
385         windowCollector.add(window);
386         eViewCollection.fireEvent();
387     }
388 
389     public void removeFromWindowCollector(Gui4jWindowInternal window)
390     {
391         windowCollector.remove(window);
392         mLogger.debug(
393             "Removing window from list. Current length (after removing is): " + windowCollector.size());
394         eViewCollection.fireEvent();
395     }
396 
397     
398     /* (non-Javadoc)
399      * @see org.gui4j.Gui4j#createView(java.lang.String, org.gui4j.Gui4jController, java.lang.String, boolean)
400      */
401     public Gui4jView createView(String viewResourceName, Gui4jController gui4jController, String title,
402             boolean readOnlyMode)
403     {
404         return new Gui4jViewImpl(this, viewResourceName, gui4jController, title, readOnlyMode);
405     }
406     
407     
408     /* (non-Javadoc)
409      * @see org.gui4j.Gui4j#createDialog(org.gui4j.Gui4jWindow, java.lang.String, org.gui4j.Gui4jController, java.lang.String, boolean)
410      */
411     public Gui4jDialog createDialog(Gui4jWindow owner, String viewResourceName, Gui4jController gui4jController,
412             String title, boolean readOnlyMode)
413     {
414         return new Gui4jDialogImpl(this, owner, viewResourceName, gui4jController, title, readOnlyMode);
415     }
416     public Gui4jCallFactory createCallFactory()
417     {
418         return new Gui4jCallParser();
419     }
420     
421     
422     /* (non-Javadoc)
423      * @see org.gui4j.Gui4j#writeDTD(java.io.File)
424      */
425     public void writeDTD(File outputFile) throws Gui4jException
426     {
427         getGui4jComponentManager().writeDTD(outputFile);
428     }
429     
430     
431     /* (non-Javadoc)
432      * @see org.gui4j.Gui4j#createValidator()
433      */
434     public Gui4jValidator createValidator()
435     {
436         return new Gui4jValidatorImpl(this);
437     }
438 }