View Javadoc

1   /*
2    * Copyright 1999-2004 The Apache Software Foundation
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.apache.commons.chain.impl;
17  
18  
19  import java.util.Collection;
20  import java.util.Iterator;
21  import org.apache.commons.chain.Chain;
22  import org.apache.commons.chain.Command;
23  import org.apache.commons.chain.Context;
24  import org.apache.commons.chain.Filter;
25  
26  
27  /***
28   * <p>Convenience base class for {@link Chain} implementations.</p>
29   *
30   * @author Craig R. McClanahan
31   * @version $Revision: 1.6 $ $Date: 2004/11/30 05:52:23 $
32   */
33  
34  public class ChainBase implements Chain {
35  
36  
37      // ----------------------------------------------------------- Constructors
38  
39  
40      /***
41       * <p>Construct a {@link Chain} with no configured {@link Command}s.</p>
42       */
43      public ChainBase() {
44  
45      }
46  
47  
48      /***
49       * <p>Construct a {@link Chain} configured with the specified
50       * {@link Command}.</p>
51       *
52       * @param command The {@link Command} to be configured
53       *
54       * @exception IllegalArgumentException if <code>command</code>
55       *  is <code>null</code>
56       */
57      public ChainBase(Command command) {
58  
59          addCommand(command);
60  
61      }
62  
63  
64      /***
65       * <p>Construct a {@link Chain} configured with the specified
66       * {@link Command}s.</p>
67       *
68       * @param commands The {@link Command}s to be configured
69       *
70       * @exception IllegalArgumentException if <code>commands</code>,
71       *  or one of the individual {@link Command} elements,
72       *  is <code>null</code>
73       */
74      public ChainBase(Command[] commands) {
75  
76          if (commands == null) {
77              throw new IllegalArgumentException();
78          }
79          for (int i = 0; i < commands.length; i++) {
80              addCommand(commands[i]);
81          }
82  
83      }
84  
85  
86      /***
87       * <p>Construct a {@link Chain} configured with the specified
88       * {@link Command}s.</p>
89       *
90       * @param commands The {@link Command}s to be configured
91       *
92       * @exception IllegalArgumentException if <code>commands</code>,
93       *  or one of the individual {@link Command} elements,
94       *  is <code>null</code>
95       */
96      public ChainBase(Collection commands) {
97  
98          if (commands == null) {
99              throw new IllegalArgumentException();
100         }
101         Iterator elements = commands.iterator();
102         while (elements.hasNext()) {
103             addCommand((Command) elements.next());
104         }
105 
106     }
107 
108 
109     // ----------------------------------------------------- Instance Variables
110 
111 
112     /***
113      * <p>The list of {@link Command}s configured for this {@link Chain}, in
114      * the order in which they may delegate processing to the remainder of
115      * the {@link Chain}.</p>
116      */
117     protected Command[] commands = new Command[0];
118 
119 
120     /***
121      * <p>Flag indicating whether the configuration of our commands list
122      * has been frozen by a call to the <code>execute()</code> method.</p>
123      */
124     protected boolean frozen = false;
125 
126 
127     // ---------------------------------------------------------- Chain Methods
128 
129 
130     // Documented in Chain interface
131     public void addCommand(Command command) {
132 
133         if (command == null) {
134             throw new IllegalArgumentException();
135         }
136         if (frozen) {
137             throw new IllegalStateException();
138         }
139         Command[] results = new Command[commands.length + 1];
140         System.arraycopy(commands, 0, results, 0, commands.length);
141         results[commands.length] = command;
142         commands = results;
143 
144     }
145 
146 
147     // Documented in Chain interface
148     public boolean execute(Context context) throws Exception {
149 
150         // Verify our parameters
151         if (context == null) {
152             throw new IllegalArgumentException();
153         }
154 
155         // Freeze the configuration of the command list
156         frozen = true;
157 
158         // Execute the commands in this list until one returns true
159         // or throws an exception
160         boolean saveResult = false;
161         Exception saveException = null;
162         int i = 0;
163         int n = commands.length;;
164         for (i = 0; i < n; i++) {
165             try {
166                 saveResult = commands[i].execute(context);
167                 if (saveResult) {
168                     break;
169                 }
170             } catch (Exception e) {
171                 saveException = e;
172                 break;
173             }
174         }
175 
176         // Call postprocess methods on Filters in reverse order
177         if (i >= n) { // Fell off the end of the chain
178             i--;
179         }
180         boolean handled = false;
181         boolean result = false;
182         for (int j = i; j >= 0; j--) {
183             if (commands[j] instanceof Filter) {
184                 try {
185                     result =
186                         ((Filter) commands[j]).postprocess(context,
187                                                            saveException);
188                     if (result) {
189                         handled = true;
190                     }
191                 } catch (Exception e) {
192                     ; // Silently ignore
193                 }
194             }
195         }
196 
197         // Return the exception or result state from the last execute()
198         if ((saveException != null) && !handled) {
199             throw saveException;
200         } else {
201             return (saveResult);
202         }
203 
204     }
205 
206 
207     // -------------------------------------------------------- Package Methods
208 
209 
210     /***
211      * <p>Return an array of the configured {@link Command}s for this
212      * {@link Chain}.  This method is package private, and is used only
213      * for the unit tests.</p>
214      */
215     Command[] getCommands() {
216 
217         return (commands);
218 
219     }
220 
221 
222 }