Home » geronimo-2.2-source-release » org.apache.geronimo.cxf » [javadoc | source]

    1   /**
    2    *  Licensed to the Apache Software Foundation (ASF) under one or more
    3    *  contributor license agreements.  See the NOTICE file distributed with
    4    *  this work for additional information regarding copyright ownership.
    5    *  The ASF licenses this file to You under the Apache License, Version 2.0
    6    *  (the "License"); you may not use this file except in compliance with
    7    *  the License.  You may obtain a copy of the License at
    8    *
    9    *     http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    *  Unless required by applicable law or agreed to in writing, software
   12    *  distributed under the License is distributed on an "AS IS" BASIS,
   13    *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    *  See the License for the specific language governing permissions and
   15    *  limitations under the License.
   16    */
   17   package org.apache.geronimo.cxf;
   18   
   19   import java.io.IOException;
   20   import java.io.InputStream;
   21   import java.io.OutputStream;
   22   import java.io.Serializable;
   23   import java.net.HttpURLConnection;
   24   import java.security.Principal;
   25   import java.util.Iterator;
   26   import java.util.List;
   27   import java.util.Map;
   28   import java.util.logging.Logger;
   29   
   30   import javax.servlet.ServletContext;
   31   import javax.servlet.http.HttpServletRequest;
   32   import javax.servlet.http.HttpServletResponse;
   33   
   34   import org.apache.cxf.Bus;
   35   import org.apache.cxf.binding.Binding;
   36   import org.apache.cxf.message.ExchangeImpl;
   37   import org.apache.cxf.message.Message;
   38   import org.apache.cxf.message.MessageImpl;
   39   import org.apache.cxf.security.SecurityContext;
   40   import org.apache.cxf.service.model.EndpointInfo;
   41   import org.apache.cxf.transport.Conduit;
   42   import org.apache.cxf.transport.ConduitInitiator;
   43   import org.apache.cxf.transport.Destination;
   44   import org.apache.cxf.transport.MessageObserver;
   45   import org.apache.cxf.transport.http.AbstractHTTPDestination;
   46   import org.apache.cxf.transport.http.HTTPSession;
   47   import org.apache.cxf.ws.addressing.EndpointReferenceType;
   48   import org.apache.geronimo.webservices.WebServiceContainer;
   49   import org.apache.geronimo.webservices.WebServiceContainer.Request;
   50   import org.apache.geronimo.webservices.WebServiceContainer.Response;
   51   
   52   public class GeronimoDestination extends AbstractHTTPDestination
   53           implements Serializable {
   54   
   55       private MessageObserver messageObserver;
   56       private boolean passSecurityContext = false;
   57       private CXFEndpoint endpoint;
   58   
   59       public GeronimoDestination(Bus bus, 
   60                                  ConduitInitiator conduitInitiator, 
   61                                  EndpointInfo endpointInfo) throws IOException {
   62           super(bus, conduitInitiator, endpointInfo, false);
   63           this.endpoint = bus.getExtension(CXFEndpoint.class);
   64       }
   65   
   66       private Binding getBinding() {
   67           return this.endpoint.getEndpoint().getBinding();
   68       }
   69       
   70       public void setPassSecurityContext(boolean passSecurityContext) {
   71           this.passSecurityContext = passSecurityContext;
   72       }
   73       
   74       public boolean getPassSecurityContext() {
   75           return this.passSecurityContext;
   76       }
   77       
   78       public EndpointInfo getEndpointInfo() {
   79           return this.endpointInfo;
   80       }
   81   
   82       public void invoke(Request request, Response response) throws Exception {
   83           MessageImpl message = new MessageImpl();
   84           message.setContent(InputStream.class, request.getInputStream());
   85           message.setDestination(this);
   86   
   87           message.put(Request.class, request);
   88           message.put(Response.class, response);
   89   
   90           final HttpServletRequest servletRequest = 
   91               (HttpServletRequest)request.getAttribute(WebServiceContainer.SERVLET_REQUEST);
   92           message.put(HTTP_REQUEST, servletRequest);
   93           
   94           HttpServletResponse servletResponse =
   95               (HttpServletResponse)request.getAttribute(WebServiceContainer.SERVLET_RESPONSE);
   96           message.put(HTTP_RESPONSE, servletResponse);
   97           
   98           ServletContext servletContext = 
   99               (ServletContext)request.getAttribute(WebServiceContainer.SERVLET_CONTEXT);
  100           message.put(HTTP_CONTEXT, servletContext);
  101           
  102           if (this.passSecurityContext) {
  103               message.put(SecurityContext.class, new SecurityContext() {
  104                   public Principal getUserPrincipal() {
  105                       return servletRequest.getUserPrincipal();
  106                   }
  107                   public boolean isUserInRole(String role) {
  108                       return servletRequest.isUserInRole(role);
  109                   }
  110               });
  111           }
  112           
  113           // this calls copyRequestHeaders()
  114           setHeaders(message);
  115           
  116           message.put(Message.HTTP_REQUEST_METHOD, servletRequest.getMethod());
  117           message.put(Message.PATH_INFO, servletRequest.getPathInfo());
  118           message.put(Message.QUERY_STRING, servletRequest.getQueryString());
  119           message.put(Message.CONTENT_TYPE, servletRequest.getContentType());
  120           message.put(Message.ENCODING, getCharacterEncoding(servletRequest.getCharacterEncoding()));
  121           
  122           ExchangeImpl exchange = new ExchangeImpl();
  123           exchange.setInMessage(getBinding().createMessage(message));
  124           exchange.setSession(new HTTPSession(servletRequest));
  125           
  126           messageObserver.onMessage(message);
  127       }
  128   
  129       private static String getCharacterEncoding(String encoding) {
  130           if (encoding != null) {
  131               encoding = encoding.trim();
  132               // work around a bug with Jetty which results in the character
  133               // encoding not being trimmed correctly:
  134               // http://jira.codehaus.org/browse/JETTY-302
  135               if (encoding.endsWith("\"")) {
  136                   encoding = encoding.substring(0, encoding.length() - 1);
  137               }
  138           }
  139           return encoding;
  140       }
  141       
  142       public Logger getLogger() {
  143           return Logger.getLogger(GeronimoDestination.class.getName());
  144       }
  145   
  146       public Conduit getInbuiltBackChannel(Message inMessage) {
  147           return new BackChannelConduit(null, inMessage);
  148       }
  149   
  150       public Conduit getBackChannel(Message inMessage,
  151                                     Message partialResponse,
  152                                     EndpointReferenceType address) throws IOException {
  153           Conduit backChannel = null;
  154           if (address == null) {
  155               backChannel = new BackChannelConduit(address, inMessage);
  156           } else {
  157               if (partialResponse != null) {
  158                   // setup the outbound message to for 202 Accepted
  159                   partialResponse.put(Message.RESPONSE_CODE,
  160                                       HttpURLConnection.HTTP_ACCEPTED);
  161                   backChannel = new BackChannelConduit(address, inMessage);
  162               } else {
  163                   backChannel = conduitInitiator.getConduit(endpointInfo, address);
  164                   // ensure decoupled back channel input stream is closed
  165                   backChannel.setMessageObserver(new MessageObserver() {
  166                       public void onMessage(Message m) {
  167                           if (m.getContentFormats().contains(InputStream.class)) {
  168                               InputStream is = m.getContent(InputStream.class);
  169                               try {
  170                                   is.close();
  171                               } catch (Exception e) {
  172                                   // ignore
  173                               }
  174                           }
  175                       }
  176                   });
  177               }
  178           }
  179           return backChannel;
  180       }
  181   
  182       public void shutdown() {
  183       }
  184   
  185       public void setMessageObserver(MessageObserver messageObserver) {
  186           this.messageObserver = messageObserver;
  187       }
  188   
  189       protected class BackChannelConduit implements Conduit {
  190   
  191           protected Message request;
  192           protected EndpointReferenceType target;
  193   
  194           BackChannelConduit(EndpointReferenceType target, Message request) {
  195               this.target = target;
  196               this.request = request;
  197           }
  198   
  199           public void close(Message msg) throws IOException {
  200               msg.getContent(OutputStream.class).close();
  201           }
  202   
  203           /**
  204            * Register a message observer for incoming messages.
  205            *
  206            * @param observer the observer to notify on receipt of incoming
  207            */
  208           public void setMessageObserver(MessageObserver observer) {
  209               // shouldn't be called for a back channel conduit
  210           }
  211           
  212           public void prepare(Message message) throws IOException {
  213               send(message);
  214           }
  215   
  216           /**
  217            * Send an outbound message, assumed to contain all the name-value
  218            * mappings of the corresponding input message (if any).
  219            *
  220            * @param message the message to be sent.
  221            */
  222           public void send(Message message) throws IOException {
  223               Response response = (Response)request.get(Response.class);
  224               
  225               // handle response headers
  226               updateResponseHeaders(message);
  227   
  228               Map<String, List<String>> protocolHeaders = 
  229                   (Map<String, List<String>>) message.get(Message.PROTOCOL_HEADERS);
  230   
  231               // set headers of the HTTP response object
  232               Iterator headers = protocolHeaders.entrySet().iterator();
  233               while (headers.hasNext()) {
  234                   Map.Entry entry = (Map.Entry) headers.next();
  235                   String headerName = (String) entry.getKey();
  236                   String headerValue = getHeaderValue((List) entry.getValue());
  237                   response.setHeader(headerName, headerValue);
  238               }
  239               
  240               message.setContent(OutputStream.class, new WrappedOutputStream(message, response));
  241           }
  242           
  243           /**
  244            * @return the reference associated with the target Destination
  245            */
  246           public EndpointReferenceType getTarget() {
  247               return target;
  248           }
  249   
  250           /**
  251            * Retreive the back-channel Destination.
  252            *
  253            * @return the backchannel Destination (or null if the backchannel is
  254            *         built-in)
  255            */
  256           public Destination getBackChannel() {
  257               return null;
  258           }
  259   
  260           /**
  261            * Close the conduit
  262            */
  263           public void close() {
  264           }
  265       }
  266           
  267       private String getHeaderValue(List<String> values) {
  268           Iterator iter = values.iterator();
  269           StringBuffer buf = new StringBuffer();
  270           while(iter.hasNext()) {
  271               buf.append(iter.next());
  272               if (iter.hasNext()) {
  273                   buf.append(", ");
  274               }
  275           }
  276           return buf.toString();
  277       }
  278       
  279       protected void setContentType(Message message, Response response) {                
  280           Map<String, List<String>> protocolHeaders =
  281               (Map<String, List<String>>)message.get(Message.PROTOCOL_HEADERS);
  282           
  283           if (protocolHeaders == null || !protocolHeaders.containsKey(Message.CONTENT_TYPE)) {
  284               String ct = (String) message.get(Message.CONTENT_TYPE);
  285               String enc = (String) message.get(Message.ENCODING);
  286               
  287               if (null != ct) {
  288                   if (enc != null && ct.indexOf("charset=") == -1) {
  289                       ct = ct + "; charset=" + enc;
  290                   }
  291                   response.setContentType(ct);
  292               } else if (enc != null) {
  293                   response.setContentType("text/xml; charset=" + enc);
  294               }
  295           }     
  296       }
  297                  
  298       private class WrappedOutputStream extends OutputStream {
  299   
  300           private Message message;
  301           private Response response;
  302           private OutputStream rawOutputStream;
  303   
  304           WrappedOutputStream(Message message, Response response) {
  305               this.message = message;
  306               this.response = response;
  307           }
  308   
  309           public void write(int b) throws IOException {
  310               flushHeaders();
  311               this.rawOutputStream.write(b);
  312           }
  313   
  314           public void write(byte b[]) throws IOException {
  315               flushHeaders();
  316               this.rawOutputStream.write(b);
  317           }
  318   
  319           public void write(byte b[], int off, int len) throws IOException {
  320               flushHeaders();
  321               this.rawOutputStream.write(b, off, len);
  322           }
  323   
  324           public void flush() throws IOException {
  325               flushHeaders();
  326               this.rawOutputStream.flush();
  327           }
  328   
  329           public void close() throws IOException {
  330               flushHeaders();
  331               this.rawOutputStream.close();
  332           }
  333           
  334            protected void flushHeaders() throws IOException {
  335               if (this.rawOutputStream != null) {
  336                   return;
  337               }
  338   
  339               // set response code
  340               Integer i = (Integer) this.message.get(Message.RESPONSE_CODE);
  341               if (i != null) {
  342                   this.response.setStatusCode(i.intValue());
  343               }
  344               
  345               // set content-type
  346               setContentType(this.message, this.response);
  347               
  348               this.rawOutputStream = this.response.getOutputStream();
  349           }
  350   
  351       }
  352          
  353   }

Home » geronimo-2.2-source-release » org.apache.geronimo.cxf » [javadoc | source]