View Javadoc

1   package org.codehaus.xfire.transport.http;
2   
3   import java.io.IOException;
4   import java.io.InputStream;
5   import java.io.UnsupportedEncodingException;
6   import java.util.Properties;
7   
8   import javax.mail.MessagingException;
9   import javax.mail.Session;
10  import javax.mail.internet.MimeMessage;
11  import javax.mail.internet.MimeMultipart;
12  import javax.servlet.ServletException;
13  import javax.servlet.http.HttpServletRequest;
14  import javax.servlet.http.HttpServletResponse;
15  import javax.xml.stream.XMLStreamException;
16  import javax.xml.stream.XMLStreamReader;
17  
18  import org.apache.commons.logging.Log;
19  import org.apache.commons.logging.LogFactory;
20  import org.codehaus.xfire.MessageContext;
21  import org.codehaus.xfire.XFire;
22  import org.codehaus.xfire.XFireRuntimeException;
23  import org.codehaus.xfire.attachments.JavaMailAttachments;
24  import org.codehaus.xfire.exchange.InMessage;
25  import org.codehaus.xfire.service.Service;
26  import org.codehaus.xfire.service.ServiceRegistry;
27  import org.codehaus.xfire.soap.SoapTransport;
28  import org.codehaus.xfire.transport.Channel;
29  import org.codehaus.xfire.transport.Transport;
30  import org.codehaus.xfire.transport.TransportManager;
31  import org.codehaus.xfire.util.STAXUtils;
32  
33  /***
34   * Loads XFire and processes requests.
35   *
36   * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a>
37   * @since Feb 13, 2004
38   */
39  public class XFireServletController
40  {
41      private static ThreadLocal requests = new ThreadLocal();
42      private static ThreadLocal responses = new ThreadLocal();
43      private final static Log logger = LogFactory.getLog(XFireServletController.class);
44      
45      protected XFire xfire;
46  
47      protected Transport transport;
48  
49      public XFireServletController(XFire xfire)
50      {
51          this.xfire = xfire;
52          this.transport = SoapTransport.createSoapTransport(new SoapHttpTransport());
53  
54          registerTransport();
55      }
56  
57      protected void registerTransport()
58      {
59          TransportManager service = getTransportManager();
60          service.register(transport);
61      }
62  
63      public static HttpServletRequest getRequest()
64      {
65          return (HttpServletRequest) requests.get();
66      }
67  
68      public static HttpServletResponse getResponse()
69      {
70          return (HttpServletResponse) responses.get();
71      }
72  
73      protected TransportManager getTransportManager()
74      {
75          return getXFire().getTransportManager();
76      }
77  
78      /***
79       * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest,
80              *      javax.servlet.http.HttpServletResponse)
81       */
82      public void doService(HttpServletRequest request,
83                            HttpServletResponse response)
84              throws ServletException, IOException
85      {
86          String serviceName = getService(request);
87          ServiceRegistry reg = getServiceRegistry();
88  
89          response.setHeader("Content-Type", "UTF-8");
90  
91          requests.set(request);
92          responses.set(response);
93  
94          if (serviceName == null || serviceName.length() == 0 || !reg.hasService(serviceName))
95          {
96              if (!reg.hasService(serviceName))
97              {
98                  response.setStatus(404);
99              }
100 
101             generateServices(response);
102             return;
103         }
104 
105         try
106         {
107             if (request.getQueryString() != null &&
108                 request.getQueryString().trim().equalsIgnoreCase("wsdl"))
109             {
110                 generateWSDL(response, serviceName);
111             }
112             else
113             {
114                 invoke(request, response, serviceName);
115             }
116         }
117         catch (Exception e)
118         {
119             logger.error("Couldn't invoke servlet request.", e);
120             
121             if (e instanceof ServletException)
122             {
123                 throw (ServletException) e;
124             }
125             else
126             {
127                 throw new ServletException(e);
128             }
129         }
130         finally
131         {
132             requests.set(null);
133             responses.set(null);
134         }
135     }
136 
137     protected void generateService(HttpServletResponse response, String serviceName)
138             throws ServletException, IOException
139 
140     {
141         response.setContentType("text/html");
142         Service endpoint = getServiceRegistry().getService(serviceName);
143         HtmlServiceWriter writer = new HtmlServiceWriter();
144         try
145         {
146             writer.write(response.getOutputStream(), endpoint);
147         }
148         catch (XMLStreamException e)
149         {
150             throw new ServletException("Error writing HTML services list", e);
151         }
152     }
153 
154 
155     /***
156      * @param response
157      */
158     protected void generateServices(HttpServletResponse response)
159             throws ServletException, IOException
160     {
161         response.setContentType("text/html");
162 
163         HtmlServiceWriter writer = new HtmlServiceWriter();
164         try
165         {
166             writer.write(response.getOutputStream(), getServiceRegistry().getServices());
167         }
168         catch (XMLStreamException e)
169         {
170             throw new ServletException("Error writing HTML services list", e);
171         }
172     }
173 
174     /***
175      * @param request
176      * @param response
177      * @param service
178      * @throws ServletException
179      * @throws IOException
180      * @throws UnsupportedEncodingException
181      */
182     protected void invoke(HttpServletRequest request,
183                           HttpServletResponse response,
184                           String service)
185             throws ServletException, IOException, UnsupportedEncodingException
186     {
187         // TODO: Return 500 on a fault
188         // TODO: Determine if the request is a soap request
189         // and if not responsed appropriately
190         
191         response.setStatus(200);
192         // response.setBufferSize(1024 * 8);
193 
194         XFireHttpSession session = new XFireHttpSession(request);
195         MessageContext context = new MessageContext();
196         context.setXFire(getXFire());
197         context.setSession(session);
198         context.setService(getService(service));
199         
200         Channel channel;
201         try
202         {
203             channel = transport.createChannel(request.getRequestURI());
204         }
205         catch (Exception e)
206         {
207             throw new ServletException("Couldn't open channel.", e);
208         }
209         
210         String contentType = request.getContentType();
211         if (null == contentType)
212         {
213             response.setContentType("text/html; charset=UTF-8");
214             // TODO: generate service description here
215             
216             response.getWriter().write("<html><body>Invalid SOAP request.</body></html>");
217             response.getWriter().close();
218         }
219         else if (contentType.toLowerCase().indexOf("multipart/related") != -1)
220         {
221             try
222             {
223                 response.setContentType("text/xml; charset=UTF-8");
224                 InputStream stream = createMIMERequest(request, context);
225                 
226                 XMLStreamReader reader = 
227                     STAXUtils.createXMLStreamReader(stream, request.getCharacterEncoding());
228                 InMessage message = new InMessage(reader, request.getRequestURI());
229                 channel.receive(context, message);
230             }
231             catch (MessagingException e)
232             {
233                 throw new XFireRuntimeException("Couldn't parse request message.", e);
234             }
235         }
236         else
237         {
238             response.setContentType("text/xml; charset=UTF-8");
239             XMLStreamReader reader = 
240                 STAXUtils.createXMLStreamReader(request.getInputStream(), 
241                                                 request.getCharacterEncoding());
242             
243             InMessage message = new InMessage(reader, request.getRequestURI());
244             channel.receive(context, message);
245         }
246     }
247 
248     protected InputStream createMIMERequest(HttpServletRequest request, MessageContext context)
249             throws MessagingException, IOException
250     {
251         Session session = Session.getDefaultInstance(new Properties(), null);
252         MimeMessage inMsg = new MimeMessage(session, request.getInputStream());
253         inMsg.addHeaderLine("Content-Type: " + request.getContentType());
254 
255         final Object content = inMsg.getContent();
256 
257         if (content instanceof MimeMultipart)
258         {
259             MimeMultipart inMP = (MimeMultipart) content;
260 
261             JavaMailAttachments atts = new JavaMailAttachments(inMP);
262             context.setProperty(JavaMailAttachments.ATTACHMENTS_KEY, atts);
263 
264             return atts.getSoapMessage().getDataHandler().getInputStream();
265         }
266         else
267         {
268             throw new UnsupportedOperationException();
269             //TODO set 500 and bail
270         }
271     }
272 
273     /***
274      * @param response
275      * @param service
276      * @throws ServletException
277      * @throws IOException
278      */
279     protected void generateWSDL(HttpServletResponse response, String service)
280             throws ServletException, IOException
281     {
282         response.setStatus(200);
283         response.setContentType("text/xml");
284 
285         getXFire().generateWSDL(service, response.getOutputStream());
286     }
287 
288     /***
289      * Get the service that is mapped to the specified request.
290      */
291     protected String getService(HttpServletRequest request)
292     {
293         String pathInfo = request.getPathInfo();
294 
295         if (pathInfo == null)
296             return null;
297 
298         String serviceName;
299 
300         if (pathInfo.startsWith("/"))
301         {
302             serviceName = pathInfo.substring(1);
303         }
304         else
305         {
306             serviceName = pathInfo;
307         }
308 
309         return serviceName;
310     }
311 
312     protected Service getService(String name)
313     {
314         return getXFire().getServiceRegistry().getService(name);
315     }
316 
317     public XFire getXFire()
318     {
319         return xfire;
320     }
321 
322     public ServiceRegistry getServiceRegistry()
323     {
324         return xfire.getServiceRegistry();
325     }
326 }