Source code: com/aendvari/satyr/servlet/gateway/HttpFormGateway.java
1 /*
2 * HttpFormGateway.java
3 *
4 * Copyright (c) 2001, 2002 Aendvari, Ltd. All Rights Reserved.
5 *
6 * See the file LICENSE for terms of use.
7 *
8 */
9
10 package com.aendvari.satyr.servlet.gateway;
11
12 import java.util.Enumeration;
13 import java.util.HashMap;
14 import java.util.Iterator;
15
16 import javax.servlet.*;
17 import javax.servlet.http.*;
18
19 import com.aendvari.hermes.broker.*;
20 import com.aendvari.hermes.broker.http.HttpMessageBrokerContext;
21
22 import com.aendvari.common.util.UrlUtil;
23
24
25 /**
26 * An HTTP form POST to message gateway. This class provides various extension
27 * points to allow application specific processing to be performed during
28 * message processing.
29 *
30 * @author Trevor Milne
31 *
32 */
33
34 public class HttpFormGateway
35 {
36 /* Constants */
37
38
39 /** Constants for POST field processing. */
40 public interface Fields
41 {
42 /** The name of "message" fields */
43 final static String SatyrMessage = "satyr/message";
44 }
45
46
47 /* Extension classes */
48
49
50 /**
51 * Defines an interface to provide a extension hook into the message processing.
52 * This is called after the messages have been extracted from the HTTP POST.
53 *
54 */
55
56 public interface Processor
57 {
58 /**
59 * Performs additional processing.
60 *
61 * @param messages The {@link Message Messages} from the HTTP POST.
62 * @param servletConfig The servlet configuration being used.
63 * @param request The servlet request we are processing.
64 * @param response The servlet response we are creating.
65 *
66 * @exception ServletException If a servlet exception occurs.
67 *
68 */
69
70 public void process(
71 HashMap messages,
72 ServletConfig servletConfig,
73 HttpServletRequest request, HttpServletResponse response)
74 throws ServletException;
75 }
76
77 /**
78 * Defines an interface to provide a context modification hook into the message processing.
79 * This is called at the beginning of the process when the connection to the message broker
80 * is established.
81 *
82 */
83
84 public interface ContextModifier
85 {
86 /**
87 * Modifies the supplied {@link MessageBrokerContext}.
88 *
89 * @param context The {@link MessageBrokerContext} to modify.
90 * @param servletConfig The servlet configuration being used.
91 * @param request The servlet request we are processing.
92 * @param response The servlet response we are creating.
93 *
94 * @exception ServletException If a servlet exception occurs.
95 *
96 */
97
98 public void modifyContext(
99 MessageBrokerContext context,
100 ServletConfig servletConfig,
101 HttpServletRequest request, HttpServletResponse response)
102 throws ServletException;
103 }
104
105 /**
106 * Defines an interface to provide a message modification hook into the message processing.
107 * This is called just prior to the message being published.
108 *
109 */
110
111 public interface MessageModifier
112 {
113 /**
114 * Modifies the supplied {@link Message}.
115 *
116 * @param message The {@link Message} to modify.
117 * @param servletConfig The servlet configuration being used.
118 * @param request The servlet request we are processing.
119 * @param response The servlet response we are creating.
120 *
121 * @exception ServletException If a servlet exception occurs.
122 *
123 */
124
125 public void modifyMessage(
126 Message message,
127 ServletConfig servletConfig,
128 HttpServletRequest request, HttpServletResponse response)
129 throws ServletException;
130 }
131
132
133 /* Processing */
134
135
136 /**
137 * Processes an HTTP request.
138 *
139 * A {@link Processor} may be provided to add additional functionality during processing.
140 * A {@link ContextModifier} may be provided to add addition information to the {@link MessageBrokerContext} created during processing.
141 * A {@link MessageModifier} may be provided to add addition information to {@link Message Messages} published during processing.
142 *
143 * @param broker The {@link MessageBroker} for publishing.
144 * @param servletConfig The servlet configuration being used.
145 * @param request The servlet request we are processing.
146 * @param response The servlet response we are creating.
147 * @param processor A {@link Processor} hook in. May be null.
148 * @param contextModifier A {@link ContextModifier} hook in. May be null.
149 * @param messageModifier A {@link Message} hook in. May be null.
150 *
151 * @exception ServletException If a servlet exception occurs.
152 *
153 */
154
155 public static void process(
156 MessageBroker broker, ServletConfig servletConfig, HttpServletRequest request, HttpServletResponse response,
157 Processor processor, ContextModifier contextModifier, MessageModifier messageModifier)
158 throws ServletException
159 {
160 // get the parameters from the reaqest
161 Enumeration parameterNames = request.getParameterNames();
162
163 // create a connection to the message broker
164 MessageBrokerConnection connection = broker.createConnection();
165
166 // create a context for the connection
167 HttpMessageBrokerContext brokerContext = new HttpMessageBrokerContext();
168
169 brokerContext.setServletConfig(servletConfig);
170 brokerContext.setRequest(request);
171 brokerContext.setResponse(response);
172 brokerContext.setSession(request.getSession());
173
174 // call context modifier hook if provided
175 if (contextModifier != null)
176 {
177 contextModifier.modifyContext(brokerContext, servletConfig, request, response);
178 }
179
180 // set the context into the connection
181 connection.setContext(brokerContext);
182
183 // create a map to hold all the Message objects
184 HashMap messages = new HashMap();
185
186 // parse message form fields
187
188 // for each field sent from the form submission
189 while (parameterNames.hasMoreElements())
190 {
191 String name = (String)parameterNames.nextElement();
192 String parameterValues[] = request.getParameterValues(name);
193
194 // process any message form fields
195 if (name.indexOf(Fields.SatyrMessage) != -1)
196 {
197 int valueIndex;
198
199 for (valueIndex = 0; valueIndex < parameterValues.length; valueIndex++)
200 {
201 // get the topic for the message
202 String topicPath = name.substring(name.indexOf(":") + 1);
203
204 // get the name/value pairs from the data string
205 HashMap nameValuePairs = UrlUtil.getNameValuePairs(
206 parameterValues[valueIndex], ";", "=", true);
207
208 // create a new message and message topic
209 Message message = connection.createMessage();
210 MessageTopic topic = connection.getTopic(topicPath);
211
212 // go through each name/value pair and add them to the message
213 Iterator nameValuePairIterator = nameValuePairs.keySet().iterator();
214 while (nameValuePairIterator.hasNext())
215 {
216 String fieldName = (String)nameValuePairIterator.next();
217 String fieldValue = (String)nameValuePairs.get(fieldName);
218
219 message.getProperties().setString(fieldName, fieldValue);
220 }
221
222 // add this message to the message list
223 // use the message as the key because topics can/may be shared by
224 // the same message. This way each message will be treated as its own
225 messages.put(message, topic);
226 }
227 }
228 }
229
230 // call processing hook if provided
231 if (processor != null)
232 {
233 processor.process(messages, servletConfig, request, response);
234 }
235
236 // start a transaction
237 connection.getTransaction().start();
238
239 // publish each message now that all fields have been processed
240 Iterator messagesIterator = messages.keySet().iterator();
241
242 while (messagesIterator.hasNext())
243 {
244 Message message = (Message)messagesIterator.next();
245 MessageTopic topic = (MessageTopic)messages.get(message);
246
247 // allow modification before publishing
248 if (messageModifier != null)
249 {
250 messageModifier.modifyMessage(message, servletConfig, request, response);
251 }
252
253 // publish the message
254 connection.publish(topic, message);
255 }
256
257 // tell the transaction to send all messages now
258 connection.getTransaction().commit();
259 }
260 }
261