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 }