001/* 002 * jDTAUS Core RI JDK 1.4 Executor 003 * Copyright (C) 2005 Christian Schulte 004 * <cs@schulte.it> 005 * 006 * This library is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 2.1 of the License, or any later version. 010 * 011 * This library is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with this library; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 019 * 020 */ 021package org.jdtaus.core.lang.ri.executor; 022 023import java.util.ArrayList; 024import java.util.List; 025import javax.swing.event.EventListenerList; 026import org.jdtaus.core.container.ContainerFactory; 027import org.jdtaus.core.lang.ExceptionEvent; 028import org.jdtaus.core.lang.ExceptionListener; 029import org.jdtaus.core.lang.spi.Executor; 030 031/** 032 * jDTAUS Core SPI JDK 1.4 {@code Executor} reference implementation. 033 * 034 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> 035 * @version $JDTAUS: Jdk14Executor.java 8641 2012-09-27 06:45:17Z schulte $ 036 * 037 * @see org.jdtaus.core.container.Container 038 */ 039public class Jdk14Executor implements Executor 040{ 041 //--Constructors------------------------------------------------------------ 042 043// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausConstructors 044 // This section is managed by jdtaus-container-mojo. 045 046 /** Standard implementation constructor <code>org.jdtaus.core.lang.ri.executor.Jdk14Executor</code>. */ 047 public Jdk14Executor() 048 { 049 super(); 050 } 051 052// </editor-fold>//GEN-END:jdtausConstructors 053 054 //------------------------------------------------------------Constructors-- 055 //--Properties-------------------------------------------------------------- 056 057// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausProperties 058 // This section is managed by jdtaus-container-mojo. 059 060 /** 061 * Gets the value of property <code>defaultThreadGroupName</code>. 062 * 063 * @return Default name of the thread group backing the implementation. 064 */ 065 private java.lang.String getDefaultThreadGroupName() 066 { 067 return (java.lang.String) ContainerFactory.getContainer(). 068 getProperty( this, "defaultThreadGroupName" ); 069 070 } 071 072// </editor-fold>//GEN-END:jdtausProperties 073 074 //--------------------------------------------------------------Properties-- 075 //--ExceptionEventSource---------------------------------------------------- 076 077 /** Holds {@code ExceptionListener}s. */ 078 private final EventListenerList listeners = new EventListenerList(); 079 080 public void addExceptionListener( final ExceptionListener listener ) 081 { 082 if ( listener == null ) 083 { 084 throw new NullPointerException( "listener" ); 085 } 086 087 synchronized ( this.listeners ) 088 { 089 this.listeners.add( ExceptionListener.class, listener ); 090 } 091 } 092 093 public void removeExceptionListener( final ExceptionListener listener ) 094 { 095 if ( listener == null ) 096 { 097 throw new NullPointerException( "listener" ); 098 } 099 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}