001    /*
002     * Copyright 1999-2001,2004 The Apache Software Foundation.
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     * 
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.apache.commons.workflow.util;
018    
019    
020    import java.util.Map;
021    import org.apache.commons.workflow.Context;
022    import org.apache.commons.workflow.ContextEvent;
023    import org.apache.commons.workflow.ContextListener;
024    import org.apache.commons.workflow.Step;
025    import org.apache.commons.workflow.StepException;
026    
027    
028    /**
029     * <strong>ContextSupport</strong> is a convenience class for managing the
030     * firing of <code>ContextEvents</code> to registered
031     * <code>ContextListeners</code>.
032     *
033     * @version $Revision: 155475 $ $Date: 2005-02-26 13:31:11 +0000 (Sat, 26 Feb 2005) $
034     * @author Craig R. McClanahan
035     */
036    
037    public class ContextSupport {
038    
039    
040        // ----------------------------------------------------------- Constructors
041    
042    
043        /**
044         * Construct a new ContextSupport object associated with the
045         * specified Context.
046         *
047         * @param context Context for whom we will fire events
048         */
049        public ContextSupport(Context context) {
050    
051            super();
052            this.context = context;
053    
054        }
055    
056    
057        // ----------------------------------------------------- Instance Variables
058    
059    
060        /**
061         * The set of registered <code>ContextListener</code> event listeners.
062         */
063        protected ContextListener listeners[] = new ContextListener[0];
064    
065    
066        /**
067         * The <code>Context</code> for whom we will fire events.
068         */
069        protected Context context = null;
070    
071    
072        // ------------------------------------------------- Event Listener Methods
073    
074    
075        /**
076         * Add a listener that is notified each time beans are added,
077         * replaced, or removed in this context.
078         *
079         * @param listener The ContextListener to be added
080         */
081        public void addContextListener(ContextListener listener) {
082    
083          synchronized (listeners) {
084              ContextListener results[] =
085                new ContextListener[listeners.length + 1];
086              System.arraycopy(listeners, 0, results, 0, listeners.length);
087              results[listeners.length] = listener;
088              listeners = results;
089          }
090    
091        }
092    
093    
094        /**
095         * Remove a listener that is notified each time beans are added,
096         * replaced, or removed in this context.
097         *
098         * @param listener The ContextListener to be removed
099         */
100        public void removeContextListener(ContextListener listener) {
101    
102            synchronized (listeners) {
103                int n = -1;
104                for (int i = 0; i < listeners.length; i++) {
105                    if (listeners[i] == listener) {
106                        n = i;
107                        break;
108                    }
109                }
110                if (n < 0)
111                    return;
112                ContextListener results[] =
113                  new ContextListener[listeners.length - 1];
114                int j = 0;
115                for (int i = 0; i < listeners.length; i++) {
116                    if (i != n)
117                        results[j++] = listeners[i];
118                }
119                listeners = results;
120            }
121    
122        }
123    
124    
125        // --------------------------------------------------- Event Firing Methods
126    
127    
128        /**
129         * Fire a <code>afterActivity</code> event to all registered listeners.
130         *
131         * @param step Step that was executed last
132         */
133        public void fireAfterActivity(Step step) {
134    
135            if (listeners.length == 0)
136                return;
137            ContextEvent event = new ContextEvent(context, step);
138            ContextListener interested[] = null;
139            synchronized (listeners) {
140                interested = (ContextListener[]) listeners.clone();
141            }
142            for (int i = 0; i < interested.length; i++)
143                interested[i].afterActivity(event);
144    
145        }
146    
147    
148        /**
149         * Fire a <code>afterActivity</code> event to all registered listeners.
150         *
151         * @param step Step that was executed last
152         * @param exception StepException thrown by the last Step
153         */
154        public void fireAfterActivity(Step step, StepException exception) {
155    
156            if (listeners.length == 0)
157                return;
158            ContextEvent event = new ContextEvent(context, step, exception);
159            ContextListener interested[] = null;
160            synchronized (listeners) {
161                interested = (ContextListener[]) listeners.clone();
162            }
163            for (int i = 0; i < interested.length; i++)
164                interested[i].afterActivity(event);
165    
166        }
167    
168    
169        /**
170         * Fire a <code>afterStep</code> event to all registered listeners.
171         *
172         * @param step Step that was executed
173         */
174        public void fireAfterStep(Step step) {
175    
176            if (listeners.length == 0)
177                return;
178            ContextEvent event = new ContextEvent(context, step);
179            ContextListener interested[] = null;
180            synchronized (listeners) {
181                interested = (ContextListener[]) listeners.clone();
182            }
183            for (int i = 0; i < interested.length; i++)
184                interested[i].afterStep(event);
185    
186        }
187    
188    
189        /**
190         * Fire a <code>afterStep</code> event to all registered listeners.
191         *
192         * @param step Step that was executed
193         * @param exception StepException thrown by the executed step
194         */
195        public void fireAfterStep(Step step, StepException exception) {
196    
197            if (listeners.length == 0)
198                return;
199            ContextEvent event = new ContextEvent(context, step, exception);
200            ContextListener interested[] = null;
201            synchronized (listeners) {
202                interested = (ContextListener[]) listeners.clone();
203            }
204            for (int i = 0; i < interested.length; i++)
205                interested[i].afterStep(event);
206    
207        }
208    
209    
210        /**
211         * Fire a <code>beforeActivity</code> event to all registered listeners.
212         *
213         * @param step Step that will be executed first
214         */
215        public void fireBeforeActivity(Step step) {
216    
217            if (listeners.length == 0)
218                return;
219            ContextEvent event = new ContextEvent(context, step);
220            ContextListener interested[] = null;
221            synchronized (listeners) {
222                interested = (ContextListener[]) listeners.clone();
223            }
224            for (int i = 0; i < interested.length; i++)
225                interested[i].beforeActivity(event);
226    
227        }
228    
229    
230        /**
231         * Fire a <code>beforeStep</code> event to all registered listeners.
232         *
233         * @param step Step that is about to be executed
234         */
235        public void fireBeforeStep(Step step) {
236    
237            if (listeners.length == 0)
238                return;
239            ContextEvent event = new ContextEvent(context, step);
240            ContextListener interested[] = null;
241            synchronized (listeners) {
242                interested = (ContextListener[]) listeners.clone();
243            }
244            for (int i = 0; i < interested.length; i++)
245                interested[i].beforeStep(event);
246    
247        }
248    
249    
250    }