Source code: org/apache/axis/SimpleChain.java
1 /*
2 * Copyright 2001-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
17 package org.apache.axis ;
18
19 import org.apache.axis.components.logger.LogFactory;
20 import org.apache.axis.handlers.BasicHandler;
21 import org.apache.axis.strategies.InvocationStrategy;
22 import org.apache.axis.strategies.WSDLGenStrategy;
23 import org.apache.axis.utils.Messages;
24 import org.apache.commons.logging.Log;
25 import org.w3c.dom.Document;
26 import org.w3c.dom.Element;
27
28 import javax.xml.namespace.QName;
29 import java.util.Enumeration;
30 import java.util.Vector;
31
32 /**
33 * A Simple Chain is a 'composite' Handler in that it aggregates a collection
34 * of Handlers and also acts as a Handler which delegates its operations to
35 * the collection.
36 * <p>
37 * A Simple Chain initially has no Handlers. Handlers may be added until the
38 * chain is invoke()d after which Handlers may not be added (and any attempt
39 * to do so will throw an exception).
40 *
41 * @author Doug Davis (dug@us.ibm.com)
42 * @author Glyn Normington (norm@uk.ibm.com)
43 */
44 public class SimpleChain extends BasicHandler implements Chain {
45 private static Log log =
46 LogFactory.getLog(SimpleChain.class.getName());
47
48 protected Vector handlers = new Vector();
49 protected boolean invoked = false;
50
51 private String CAUGHTFAULT_PROPERTY =
52 "org.apache.axis.SimpleChain.caughtFaultInResponse";
53
54 public void init() {
55 for ( int i = 0 ; i < handlers.size() ; i++ )
56 ((Handler) handlers.elementAt( i )).init();
57 }
58
59 public void cleanup() {
60 for ( int i = 0 ; i < handlers.size() ; i++ )
61 ((Handler) handlers.elementAt( i )).cleanup();
62 }
63
64 private static final HandlerIterationStrategy iVisitor =
65 new InvocationStrategy();
66
67 private static final HandlerIterationStrategy wsdlVisitor =
68 new WSDLGenStrategy();
69
70 /**
71 * Iterate over the chain invoking each handler. If there's a fault
72 * then call 'onFault' for each completed handler in reverse order, then
73 * rethrow the exception.
74 *
75 * @throws AxisFault if there was a fault with any of the handlers
76 */
77 public void invoke(MessageContext msgContext) throws AxisFault {
78 if (log.isDebugEnabled()) {
79 log.debug("Enter: SimpleChain::invoke");
80 }
81
82 invoked = true;
83 doVisiting(msgContext, iVisitor);
84
85 if (log.isDebugEnabled()) {
86 log.debug("Exit: SimpleChain::invoke");
87 }
88 }
89
90 /**
91 * Iterate over the chain letting each handler have a crack at
92 * contributing to a WSDL description.
93 *
94 * @param msgContext the <code>MessageContext</code> to write the WSDL
95 * out to
96 * @throws AxisFault if there was a problem writing the WSDL
97 */
98 public void generateWSDL(MessageContext msgContext) throws AxisFault {
99 if (log.isDebugEnabled()) {
100 log.debug("Enter: SimpleChain::generateWSDL");
101 }
102
103 invoked = true;
104 doVisiting(msgContext, wsdlVisitor);
105
106 if (log.isDebugEnabled()) {
107 log.debug("Exit: SimpleChain::generateWSDL");
108 }
109 }
110
111 private void doVisiting(MessageContext msgContext,
112 HandlerIterationStrategy visitor) throws AxisFault {
113 int i = 0 ;
114 try {
115 Enumeration enumeration = handlers.elements();
116 while (enumeration.hasMoreElements()) {
117 Handler h = (Handler)enumeration.nextElement();
118 visitor.visit(h, msgContext);
119 i++;
120 }
121 } catch( AxisFault f ) {
122 // Something went wrong. If we haven't already put this fault
123 // into the MessageContext's response message, do so and make sure
124 // we only do it once. This allows onFault() methods to safely
125 // set headers and such in the response message without them
126 // getting stomped.
127 if (!msgContext.isPropertyTrue(CAUGHTFAULT_PROPERTY)) {
128 // Attach the fault to the response message; enabling access to the
129 // fault details while inside the handler onFault methods.
130 Message respMsg = new Message(f);
131 msgContext.setResponseMessage(respMsg);
132 msgContext.setProperty(CAUGHTFAULT_PROPERTY, Boolean.TRUE);
133 }
134 while( --i >= 0 )
135 ((Handler) handlers.elementAt( i )).onFault( msgContext );
136 throw f;
137 }
138 }
139
140 /**
141 * Notify the handlers in this chain because some handler
142 * later on has faulted - in reverse order. If any handlers
143 * have been added since we visited the chain, they will get
144 * notified too!
145 *
146 * @param msgContext the context to process
147 */
148 public void onFault(MessageContext msgContext) {
149 if (log.isDebugEnabled()) {
150 log.debug("Enter: SimpleChain::onFault");
151 }
152
153 for ( int i = handlers.size()-1 ; i >= 0 ; i-- )
154 ((Handler) handlers.elementAt( i )).onFault( msgContext );
155
156 if (log.isDebugEnabled()) {
157 log.debug("Exit: SimpleChain::onFault");
158 }
159 }
160
161 public boolean canHandleBlock(QName qname) {
162 for ( int i = 0 ; i < handlers.size() ; i++ )
163 if ( ((Handler) handlers.elementAt( i )).canHandleBlock(qname) )
164 return( true );
165 return( false );
166 }
167
168 public void addHandler(Handler handler) {
169 if (handler == null)
170 throw new InternalException(
171 Messages.getMessage("nullHandler00",
172 "SimpleChain::addHandler"));
173
174 if (invoked)
175 throw new InternalException(
176 Messages.getMessage("addAfterInvoke00",
177 "SimpleChain::addHandler"));
178
179 handlers.add( handler );
180 }
181
182 public boolean contains(Handler handler) {
183 return( handlers.contains( handler ));
184 }
185
186 public Handler[] getHandlers() {
187 if (handlers.size() == 0)
188 return null;
189
190 Handler [] ret = new Handler[handlers.size()];
191 return( (Handler[]) handlers.toArray(ret) );
192 }
193
194 public Element getDeploymentData(Document doc) {
195 if (log.isDebugEnabled()) {
196 log.debug( Messages.getMessage("enter00",
197 "SimpleChain::getDeploymentData") );
198 }
199
200 Element root = doc.createElementNS("", "chain" );
201
202 StringBuffer str = new StringBuffer();
203 int i = 0;
204 while (i < handlers.size()) {
205 if ( i != 0 ) str.append(",");
206 Handler h = (Handler) handlers.elementAt(i);
207 str.append( h.getName() );
208 i++;
209 }
210 if (i > 0) {
211 root.setAttribute( "flow", str.toString() );
212 }
213
214 if ( options != null ) {
215 Enumeration e = options.keys();
216 while ( e.hasMoreElements() ) {
217 String k = (String) e.nextElement();
218 Object v = options.get(k);
219 Element e1 = doc.createElementNS("", "option");
220 e1.setAttribute( "name", k );
221 e1.setAttribute( "value", v.toString() );
222 root.appendChild( e1 );
223 }
224 }
225
226 if (log.isDebugEnabled()) {
227 log.debug("Exit: SimpleChain::getDeploymentData");
228 }
229
230 return( root );
231 }
232 }