View Javadoc

1   /*
2    *  jDTAUS Core RI JDK 1.4 Executor
3    *  Copyright (C) 2005 Christian Schulte
4    *  <cs@schulte.it>
5    *
6    *  This library is free software; you can redistribute it and/or
7    *  modify it under the terms of the GNU Lesser General Public
8    *  License as published by the Free Software Foundation; either
9    *  version 2.1 of the License, or any later version.
10   *
11   *  This library is distributed in the hope that it will be useful,
12   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   *  Lesser General Public License for more details.
15   *
16   *  You should have received a copy of the GNU Lesser General Public
17   *  License along with this library; if not, write to the Free Software
18   *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19   *
20   */
21  package org.jdtaus.core.lang.ri.executor;
22  
23  import java.util.ArrayList;
24  import java.util.List;
25  import javax.swing.event.EventListenerList;
26  import org.jdtaus.core.container.ContainerFactory;
27  import org.jdtaus.core.lang.ExceptionEvent;
28  import org.jdtaus.core.lang.ExceptionListener;
29  import org.jdtaus.core.lang.spi.Executor;
30  
31  /**
32   * jDTAUS Core SPI JDK 1.4 {@code Executor} reference implementation.
33   *
34   * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
35   * @version $JDTAUS: Jdk14Executor.java 8641 2012-09-27 06:45:17Z schulte $
36   *
37   * @see org.jdtaus.core.container.Container
38   */
39  public class Jdk14Executor implements Executor
40  {
41      //--Constructors------------------------------------------------------------
42  
43  // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausConstructors
44      // This section is managed by jdtaus-container-mojo.
45  
46      /** Standard implementation constructor <code>org.jdtaus.core.lang.ri.executor.Jdk14Executor</code>. */
47      public Jdk14Executor()
48      {
49          super();
50      }
51  
52  // </editor-fold>//GEN-END:jdtausConstructors
53  
54      //------------------------------------------------------------Constructors--
55      //--Properties--------------------------------------------------------------
56  
57  // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausProperties
58      // This section is managed by jdtaus-container-mojo.
59  
60      /**
61       * Gets the value of property <code>defaultThreadGroupName</code>.
62       *
63       * @return Default name of the thread group backing the implementation.
64       */
65      private java.lang.String getDefaultThreadGroupName()
66      {
67          return (java.lang.String) ContainerFactory.getContainer().
68              getProperty( this, "defaultThreadGroupName" );
69  
70      }
71  
72  // </editor-fold>//GEN-END:jdtausProperties
73  
74      //--------------------------------------------------------------Properties--
75      //--ExceptionEventSource----------------------------------------------------
76  
77      /** Holds {@code ExceptionListener}s. */
78      private final EventListenerList listeners = new EventListenerList();
79  
80      public void addExceptionListener( final ExceptionListener listener )
81      {
82          if ( listener == null )
83          {
84              throw new NullPointerException( "listener" );
85          }
86  
87          synchronized ( this.listeners )
88          {
89              this.listeners.add( ExceptionListener.class, listener );
90          }
91      }
92  
93      public void removeExceptionListener( final ExceptionListener listener )
94      {
95          if ( listener == null )
96          {
97              throw new NullPointerException( "listener" );
98          }
99  
100         synchronized ( this.listeners )
101         {
102             this.listeners.remove( ExceptionListener.class, listener );
103         }
104     }
105 
106     public ExceptionListener[] getExceptionListeners()
107     {
108         synchronized ( this.listeners )
109         {
110             return (ExceptionListener[]) this.listeners.getListeners(
111                 ExceptionListener.class );
112 
113         }
114     }
115 
116     //----------------------------------------------------ExceptionEventSource--
117     //--ExceptionHandler--------------------------------------------------------
118 
119     /** List of exception handled by the instance. */
120     private final List handledExceptions = new ArrayList( 255 );
121 
122     public ExceptionEvent[] getExceptionEvents()
123     {
124         synchronized ( this.handledExceptions )
125         {
126             return (ExceptionEvent[]) this.handledExceptions.toArray(
127                 new ExceptionEvent[ this.handledExceptions.size() ] );
128 
129         }
130     }
131 
132     public void handle( final Throwable t )
133     {
134         if ( t == null )
135         {
136             throw new NullPointerException( "t" );
137         }
138 
139         final ExceptionEvent evt =
140             new ExceptionEvent( this, Thread.currentThread(), t );
141 
142         this.fireOnException( evt );
143     }
144 
145     //--------------------------------------------------------ExceptionHandler--
146     //--Executor----------------------------------------------------------------
147 
148     public void executeAsynchronously( final Runnable runnable )
149     {
150         if ( runnable == null )
151         {
152             throw new NullPointerException( "runnable" );
153         }
154 
155         new Thread( this.getThreadGroup(), runnable ).start();
156     }
157 
158     //----------------------------------------------------------------Executor--
159     //--Jdk14Executor-----------------------------------------------------------
160 
161     /** The name of the thread group backing the instance. */
162     private String threadGroupName;
163 
164     /**
165      * {@code ThreadGroup} of threads executing the given {@code Runnable}s
166      * asynchronously.
167      */
168     private ThreadGroup threadGroup;
169 
170     /**
171      * Creates a new {@code Jdk14Executor} instance taking the name of the
172      * thread group backing the instance.
173      *
174      * @param threadGroupName the name of the thread group backing the instance.
175      */
176     public Jdk14Executor( final String threadGroupName )
177     {
178         if ( threadGroupName != null )
179         {
180             this.threadGroupName = threadGroupName;
181         }
182     }
183 
184     /**
185      * Group of threads executing the given {@code Runnable}s asynchronously.
186      */
187     private final class ThreadGroup extends java.lang.ThreadGroup
188     {
189 
190         /**
191          * Creates a new {@code ExecutorThreadGroup} instance taking its name.
192          *
193          * @param name the name of the new thread group.
194          */
195         ThreadGroup( final String name )
196         {
197             super( name );
198         }
199 
200         /**
201          * {@inheritdDoc}
202          * <p>This method notifies any registered {@code ExceptionListener}s
203          * about the given exception if it is not an instance of
204          * {@code ThreadDeath}. For instances of {@code ThreadDeath} the super
205          * classe's {@code uncaughtException(Thread, Throwable)} method is
206          * called.</p>
207          *
208          * @param t the thread that is about to exit.
209          * @param e the uncaught exception.
210          */
211         public void uncaughtException( final Thread t, final Throwable e )
212         {
213             if ( e instanceof ThreadDeath )
214             {
215                 super.uncaughtException( t, e );
216             }
217             else
218             {
219                 fireOnException(
220                     new ExceptionEvent( Jdk14Executor.this, t, e ) );
221 
222             }
223         }
224 
225     }
226 
227     /**
228      * Gets the value of property {@code threadGroupName}.
229      *
230      * @return the name of the thread group backing the instance.
231      */
232     private String getThreadGroupName()
233     {
234         if ( this.threadGroupName == null )
235         {
236             this.threadGroupName = this.getDefaultThreadGroupName();
237         }
238 
239         return this.threadGroupName;
240     }
241 
242     /**
243      * Gets the group of threads executing the given {@code Runnable}s
244      * asynchronously.
245      *
246      * @return the group of threads executing the given {@code Runnable}s
247      * asynchronously.
248      */
249     private ThreadGroup getThreadGroup()
250     {
251         if ( this.threadGroup == null )
252         {
253             this.threadGroup =
254                 new Jdk14Executor.ThreadGroup( this.getThreadGroupName() );
255 
256         }
257 
258         return this.threadGroup;
259     }
260 
261     /**
262      * Notifies all registered {@code ExceptionListener}s about a given
263      * {@code ExceptionEvent}.
264      *
265      * @param e the event to provide to the listeners.
266      *
267      * @throws NullPointerException if {@code e} is {@code null}.
268      */
269     private void fireOnException( final ExceptionEvent e )
270     {
271         if ( e == null )
272         {
273             throw new NullPointerException( "e" );
274         }
275 
276         synchronized ( this.handledExceptions )
277         {
278             this.handledExceptions.add( e );
279         }
280 
281         synchronized ( this.listeners )
282         {
283             final Object[] list = this.listeners.getListenerList();
284             for ( int i = list.length - 2; i >= 0; i -= 2 )
285             {
286                 if ( list[i] == ExceptionListener.class )
287                 {
288                     ( (ExceptionListener) list[i + 1] ).onException( e );
289                 }
290             }
291         }
292 
293         final ExceptionListener[] exceptionListener =
294             this.getExceptionListener();
295 
296         for ( int i = exceptionListener.length - 1; i >= 0; i-- )
297         {
298             exceptionListener[i].onException( e );
299         }
300     }
301 
302     //-----------------------------------------------------------Jdk14Executor--
303     //--Dependencies------------------------------------------------------------
304 
305 // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausDependencies
306     // This section is managed by jdtaus-container-mojo.
307 
308     /**
309      * Gets the configured <code>ExceptionListener</code> implementation.
310      *
311      * @return The configured <code>ExceptionListener</code> implementation.
312      */
313     private ExceptionListener[] getExceptionListener()
314     {
315         return (ExceptionListener[]) ContainerFactory.getContainer().
316             getDependency( this, "ExceptionListener" );
317 
318     }
319 
320 // </editor-fold>//GEN-END:jdtausDependencies
321 
322     //------------------------------------------------------------Dependencies--
323 }