001: /*
002: * The Apache Software License, Version 1.1
003: *
004: *
005: * Copyright (c) 2002 The Apache Software Foundation. All rights
006: * reserved.
007: *
008: * Redistribution and use in source and binary forms, with or without
009: * modification, are permitted provided that the following conditions
010: * are met:
011: *
012: * 1. Redistributions of source code must retain the above copyright
013: * notice, this list of conditions and the following disclaimer.
014: *
015: * 2. Redistributions in binary form must reproduce the above copyright
016: * notice, this list of conditions and the following disclaimer in
017: * the documentation and/or other materials provided with the
018: * distribution.
019: *
020: * 3. The end-user documentation included with the redistribution,
021: * if any, must include the following acknowledgment:
022: * "This product includes software developed by the
023: * Apache Software Foundation (http://www.apache.org/)."
024: * Alternately, this acknowledgment may appear in the software itself,
025: * if and wherever such third-party acknowledgments normally appear.
026: *
027: * 4. The names "WSIF" and "Apache Software Foundation" must
028: * not be used to endorse or promote products derived from this
029: * software without prior written permission. For written
030: * permission, please contact apache@apache.org.
031: *
032: * 5. Products derived from this software may not be called "Apache",
033: * nor may "Apache" appear in their name, without prior written
034: * permission of the Apache Software Foundation.
035: *
036: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
037: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
038: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
039: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
040: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
041: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
042: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
043: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
044: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
045: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
046: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
047: * SUCH DAMAGE.
048: * ====================================================================
049: *
050: * This software consists of voluntary contributions made by many
051: * individuals on behalf of the Apache Software Foundation and was
052: * originally based on software copyright (c) 2001, 2002, International
053: * Business Machines, Inc., http://www.apache.org. For more
054: * information on the Apache Software Foundation, please see
055: * <http://www.apache.org/>.
056: */
057:
058: package org.apache.wsif.util.jms;
059:
060: import java.net.URL;
061: import java.util.ArrayList;
062: import java.util.Arrays;
063: import java.util.HashMap;
064: import java.util.Hashtable;
065: import java.util.Iterator;
066:
067: import javax.jms.JMSException;
068: import javax.jms.Message;
069: import javax.jms.Queue;
070: import javax.jms.TextMessage;
071: import org.apache.soap.rpc.SOAPContext;
072: import org.apache.soap.transport.TransportMessage;
073: import org.apache.soap.util.IOUtils;
074: import org.apache.soap.util.net.HTTPUtils;
075: import org.apache.wsif.WSIFException;
076: import org.apache.wsif.logging.Trc;
077:
078: /**
079: * This class implements a JMS to HTTP bridge. That is it takes SOAP
080: * messages off of a JMS queue and posts them using HTTP. The SOAP message
081: * in the HTTP response is put on a JMS reply queue. This class contains a
082: * main method which takes as parameters all the JMS and HTTP information
083: * needed. This bridge can be cold or warm started. Cold starting wipes
084: * messages off queues on startup, whereas warm starting does not.
085: *
086: * @author Mark Whitlock <whitlock@apache.org>
087: */
088: public class JMS2HTTPBridge {
089: private URL httpURL = null;
090: private JMS2HTTPBridgeDestination destination = null;
091:
092: private static final ArrayList outGoingHeaders = new ArrayList(
093: Arrays.asList(new String[] { "SOAPAction" }));
094:
095: private static final ArrayList interestingProperties = new ArrayList(
096: Arrays.asList(new String[] { "JMSPriority",
097: "JMSDeliveryMode" }));
098: private boolean verbose;
099:
100: private WSIFJMSListener list = new WSIFJMSListener() {
101: public void onException(JMSException arg1) {
102: Trc.entry(this , arg1);
103: System.out.println("Caught an exception!");
104: arg1.printStackTrace();
105: Trc.exit();
106: }
107:
108: public void onMessage(Message message) {
109: Trc.entry(this , message);
110: receiveMessage(message);
111: Trc.exit();
112: }
113: };
114:
115: public JMS2HTTPBridge(String initialContextFactory, String jndiUrl,
116: String queueConnectionFactory, String readQueue,
117: String httpUrlString, String startType, boolean verbose)
118: throws Exception {
119: Trc.entry(this , initialContextFactory, jndiUrl,
120: queueConnectionFactory, readQueue, httpUrlString,
121: startType, new Boolean(verbose));
122:
123: System.out.println("Starting the JMS2HTTPBridge with" + "\n"
124: + "Initial Context Factory = " + initialContextFactory
125: + "\n" + "JNDI URL = " + jndiUrl + "\n"
126: + "Queue Connection Factory = "
127: + queueConnectionFactory + "\n" + "JNDI Read Queue = "
128: + readQueue + "\n" + "HTTP URL = " + httpUrlString
129: + "\n" + "Start Type = " + startType + "\n"
130: + "Verbose = " + verbose);
131:
132: destination = new JMS2HTTPBridgeDestination(
133: new WSIFJMSFinderForJndi(null, initialContextFactory,
134: jndiUrl, WSIFJMSFinder.STYLE_QUEUE,
135: queueConnectionFactory, readQueue, null), null,
136: WSIFJMSConstants.WAIT_FOREVER, startType, verbose);
137:
138: httpURL = new URL(httpUrlString);
139: this .verbose = verbose;
140: Trc.exit();
141: }
142:
143: public static void main(String[] args) throws Exception {
144: Trc.entry(null, args);
145:
146: String usage = "Usage: java " + JMS2HTTPBridge.class.getName()
147: + " [-cold|-warm] " + "-icf <initialContextFactory> "
148: + "-jndi <jndiUrl> " + "-s <sampleName> "
149: + "-qcf <queueConnectionFactory> " + "-q <readQueue> "
150: + "-http <httpUrl>" + "-v";
151:
152: String startType = JMS2HTTPBridgeDestination.WARMSTART;
153: String initialContextFactory = "com.sun.jndi.fscontext.RefFSContextFactory";
154: String jndiUrl = "file:///JNDI-Directory";
155: String sampleName = null;
156: String queueConnectionFactory = "WSIFSampleQCF";
157: String readQueue = null;
158: String httpUrlString = "http://localhost:8080/soap/servlet/rpcrouter";
159: boolean verbose = false;
160:
161: for (int idx = 0; idx < args.length; idx++) {
162: if (!args[idx].startsWith("-"))
163: throw new Exception("Bad parameter\n" + usage);
164:
165: if (args[idx].equals("-cold")) {
166: startType = JMS2HTTPBridgeDestination.COLDSTART;
167: } else if (args[idx].equals("-warm")) {
168: startType = JMS2HTTPBridgeDestination.WARMSTART;
169: } else if (args[idx].equals("-icf")) {
170: idx++;
171: initialContextFactory = args[idx];
172: } else if (args[idx].equals("-jndi")) {
173: idx++;
174: jndiUrl = args[idx];
175: } else if (args[idx].equals("-s")) {
176: idx++;
177: sampleName = args[idx];
178: } else if (args[idx].equals("-qcf")) {
179: idx++;
180: queueConnectionFactory = args[idx];
181: } else if (args[idx].equals("-q")) {
182: idx++;
183: readQueue = args[idx];
184: } else if (args[idx].equals("-http")) {
185: idx++;
186: httpUrlString = args[idx];
187: } else if (args[idx].equals("-v")) {
188: verbose = true;
189: } else
190: throw new Exception("Bad parameter\n" + usage);
191: }
192:
193: if (readQueue == null && sampleName != null)
194: readQueue = "SoapJms" + sampleName + "Queue";
195:
196: if (startType == null || initialContextFactory == null
197: || jndiUrl == null || queueConnectionFactory == null
198: || readQueue == null || httpUrlString == null)
199: throw new Exception("Missing parameter\n" + usage);
200:
201: JMS2HTTPBridge j2h = new JMS2HTTPBridge(initialContextFactory,
202: jndiUrl, queueConnectionFactory, readQueue,
203: httpUrlString, startType, verbose);
204:
205: j2h.listen();
206: Trc.exit();
207: }
208:
209: public void listen() throws WSIFException {
210: Trc.entry(this );
211: destination.listen(list);
212: Trc.exit();
213: }
214:
215: void receiveMessage(Message msg) {
216: Trc.entry(this , msg);
217: String payload = null;
218:
219: try {
220: if (verbose)
221: System.out.println("Caught a message!");
222:
223: if (msg instanceof TextMessage) {
224: String body = ((TextMessage) msg).getText();
225: if (body != null) {
226: if (verbose)
227: System.out.println("Message contained '" + body
228: + "'");
229:
230: TransportMessage tmsg = new TransportMessage(body,
231: new SOAPContext(), new Hashtable());
232: setOutGoingHeaders(msg, tmsg);
233: tmsg.save();
234:
235: TransportMessage response = HTTPUtils.post(
236: getServiceURL(msg), tmsg, 30000, null, 0);
237: payload = IOUtils.getStringFromReader(response
238: .getEnvelopeReader());
239: if (verbose)
240: System.out.println("HTTP RESPONSE IS: '"
241: + payload + "'");
242: } else {
243: System.err
244: .println("error: message contained no body");
245: payload = "error: message contained no body";
246: }
247: } else {
248: System.err
249: .println("error: message was not a TextMessage as expected");
250: System.err.println(msg);
251: payload = "error: message was not a TextMessage as expected";
252: }
253:
254: } catch (Exception e) {
255: e.printStackTrace();
256: payload = e.toString();
257: }
258:
259: try {
260: // Put the properties from the received message onto the message we are
261: // about to send. Filter out everything but those properties that we
262: // know about and are interested in, since there'll be lots of stuff in
263: // props that aren't really properties at all.
264: WSIFJMSProperties props = new WSIFJMSProperties(
265: WSIFJMSProperties.OUT);
266: props.getPropertiesFromMessage(msg);
267: HashMap kept = new HashMap();
268: Iterator it = interestingProperties.iterator();
269: while (true) {
270: try {
271: if (!it.hasNext())
272: break;
273: String prop = (String) it.next();
274: if (props.containsKey(prop))
275: kept.put(prop, props.get(prop));
276: } catch (Exception e) {
277: System.err
278: .println("JMS2HTTPBridge properties caught "
279: + e);
280: }
281: }
282:
283: destination.setProperties(kept);
284: destination.setReplyToQueue((Queue) msg.getJMSReplyTo());
285: destination.send(payload, msg.getJMSMessageID());
286: } catch (JMSException je) {
287: je.printStackTrace();
288: } catch (WSIFException we) {
289: we.printStackTrace();
290: }
291:
292: Trc.exit();
293: return;
294: }
295:
296: private void setOutGoingHeaders(Message m, TransportMessage tmsg) {
297: for (Iterator i = outGoingHeaders.iterator(); i.hasNext();) {
298: try {
299: String name = (String) i.next();
300: String value = m.getStringProperty(name);
301: if (value != null && value.length() > 0) {
302: tmsg.setHeader(name, "\"" + value + "\"");
303: }
304: } catch (JMSException e) {
305: Trc.ignoredException(e);
306: }
307: }
308: }
309:
310: private URL getServiceURL(Message m) {
311: URL serviceURL = null;
312: try {
313: String s = m.getStringProperty("ServiceURL");
314: serviceURL = new URL(s);
315: } catch (Exception e) {
316: Trc.ignoredException(e);
317: serviceURL = httpURL;
318: }
319: return serviceURL;
320: }
321:
322: }
|