Package org.jboss.jms.server.remoting

Source Code of org.jboss.jms.server.remoting.JMSWireFormat

/*
  * JBoss, Home of Professional Open Source
  * Copyright 2005, JBoss Inc., and individual contributors as indicated
  * by the @authors tag. See the copyright.txt in the distribution for a
  * full listing of individual contributors.
  *
  * This is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as
  * published by the Free Software Foundation; either version 2.1 of
  * the License, or (at your option) any later version.
  *
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this software; if not, write to the Free
  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  */
package org.jboss.jms.server.remoting;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;

import org.jboss.jms.wireformat.ClientDelivery;
import org.jboss.jms.wireformat.ConnectionFactoryUpdate;
import org.jboss.jms.wireformat.NullResponse;
import org.jboss.jms.wireformat.PacketSupport;
import org.jboss.jms.wireformat.PolledCallbacksDelivery;
import org.jboss.jms.wireformat.RequestSupport;
import org.jboss.jms.wireformat.ResponseSupport;
import org.jboss.jms.wireformat.SerializedPacket;
import org.jboss.logging.Logger;
import org.jboss.remoting.InvocationRequest;
import org.jboss.remoting.InvocationResponse;
import org.jboss.remoting.callback.Callback;
import org.jboss.remoting.invocation.InternalInvocation;
import org.jboss.remoting.invocation.OnewayInvocation;
import org.jboss.remoting.marshal.Marshaller;
import org.jboss.remoting.marshal.UnMarshaller;

/**
* We do not use Java or JBoss serialization to send data over the wire. Serialization adds
* considerable overhead in terms of the amount of data sent (it adds class information plus block
* data information) which significantly degrades performance.
*
* Instead we define a customer wire format that minimises the amount of data sent.
*
* The only exception to this rule is when sending an ObjectMessage which contains a user defined
* object whose type is only known at run-time. In this case we use serialization.
*
* @author <a href="tim.fox@jboss.com">Tim Fox</a>
* @author <a href="ovidiu@jboss.org">Ovidiu Feodorov</a>
* @version <tt>$Revision: 2399 $</tt>
*
* $Id: JMSWireFormat.java 2399 2007-02-23 01:21:29Z ovidiu.feodorov@jboss.com $
*/
public class JMSWireFormat implements Marshaller, UnMarshaller
{
   // Constants ------------------------------------------------------------------------------------

   private static final long serialVersionUID = -7646123424863782043L;

   private static final Logger log = Logger.getLogger(JMSWireFormat.class);
  
   // Static ---------------------------------------------------------------------------------------

   // Attributes -----------------------------------------------------------------------------------

   protected boolean trace;

   // Constructors ---------------------------------------------------------------------------------

   public JMSWireFormat()
   {
      trace = log.isTraceEnabled();
   }

   // Marshaller implementation --------------------------------------------------------------------

   public void write(Object obj, OutputStream out) throws IOException
   {         
      if (trace) { log.trace("Writing " + obj); }
     
      DataOutputStream dos;
     
      if (out instanceof DataOutputStream)
      {
         //For non HTTP transports - we should ALWAYS be passed a DataOutputStream
         //We do this by specifying socket wrapper classes on the locator uri
         dos = (DataOutputStream)out;
        
         if (trace) { log.trace("Stream is a DataOutputStream"); }
      }
      else
      {
         // Further sanity check
         if (out instanceof ObjectOutputStream)
         {
            throw new IllegalArgumentException("Invalid stream - are you sure you have " +
                                               "configured socket wrappers?");
         }
        
         // This would be the case for the HTTP transport for example. Wrap the stream.
        
         //FIXME - remoting should be fixed to allow socket wrappers to be specified for
         //all transports - not just socket
         //until then we have no choice but to create a wrapping stream on every invocation
         //for HTTP transport
         dos = new DataOutputStream(out);
        
         if (trace) { log.trace("Stream is NOT a DataOutputStream - must be using HTTP transport"); }
      }                 
     
      try
      {
         PacketSupport packet = null;
        
         if (obj instanceof InvocationRequest)
         {                       
            InvocationRequest req = (InvocationRequest)obj;
           
            Object param = req.getParameter();
           
            if (param instanceof PacketSupport)
            {
               // A JBM invocation
               packet = (PacketSupport)param;   
              
               if (trace) { log.trace("JBM Request"); }
            }
            else if (param instanceof OnewayInvocation)
            {
               if (trace) { log.trace("It's a OnewayInvocation"); }
              
               // This is fucking horrendous - remoting should not force us to deal with
               // its internal objects
              
               // Hmmm... hidden somewhere in the depths of this crap there must be the callback,
               // The search begins....

               OnewayInvocation oneWay = (OnewayInvocation)param;
              
               param = oneWay.getParameters()[0];
              
               if (param instanceof RequestSupport)
               {
                  //A JBM invocation being sent one way (e.g. changeRate, send)
                 
                  if (trace) { log.trace("JBM oneway request"); }
                 
                  packet = (PacketSupport)param;
               }
               else if (param instanceof InternalInvocation)
               {                     
                  InternalInvocation ii = (InternalInvocation)param;
                 
                  Object[] params = ii.getParameters();
                 
                  if (trace) { log.trace("Params is " + params); }
                 
                  if (params != null && params.length > 0 && params[0] instanceof Callback)
                  {
                     Callback callback = (Callback) params[0];
                    
                     if (trace) { log.trace("It's a callback: " + callback); }
                    
                     if (callback.getParameter() instanceof ClientDelivery)
                     {                       
                        packet = (ClientDelivery)callback.getParameter();
                       
                        if (trace) { log.trace("Message delivery callback"); }
                     }
                     else if (callback.getParameter() instanceof ConnectionFactoryUpdate)
                     {
                        packet = (ConnectionFactoryUpdate)callback.getParameter();
                       
                        if (trace) { log.trace("Connection factory update callback"); }
                     }
                  }
               }
               else
               {
                  throw new IllegalArgumentException("Invalid request param " + param);
               }
            }
            else
            {              
               //Some other remoting internal thing, e.g. PING, DISCONNECT, add listener etc
              
               packet = new SerializedPacket(req);              
            }
         }        
         else if (obj instanceof InvocationResponse)
         {
            InvocationResponse resp = (InvocationResponse)obj;
           
            Object param = resp.getResult();
           
            if (param instanceof ResponseSupport)
            {
               // A JBM invocation response
              
               packet = (ResponseSupport)param;
            
               if (trace) { log.trace("JBM Response"); }
            }
            else if (param instanceof List)
            {
               // List of polled Callbacks, this is how messages are delivered when using
               // polled callbacks e.g. the HTTP transport
              
               packet = new PolledCallbacksDelivery((List)param, resp.getSessionId());            
            }
            else if (param == null)
            {
               // Null response
               packet = new NullResponse();
              
               if (trace) { log.trace("Null Response"); }
            }
            else
            {
               // Return value from some remoting internal invocation e.g. PONG - return value from PING
               packet = new SerializedPacket(obj);
            }
         }
         else
         {
            //Actually this should never occur
            packet = new SerializedPacket(obj);
         }
            
         if (trace) { log.trace("Writing packet: " + packet); }
        
         packet.write(dos);
        
         if (trace) { log.trace("Wrote packet"); }
      }
      catch (Exception e)
      {
         log.error("Failed to write packet", e);
         IOException e2 = new IOException(e.getMessage());
         e2.setStackTrace(e.getStackTrace());
         throw e2;
      }
   }
  
   public Marshaller cloneMarshaller() throws CloneNotSupportedException
   {
      return this;
   }

   // UnMarshaller implementation ------------------------------------------------------------------

   public Object read(InputStream in, Map map) throws IOException, ClassNotFoundException
   {           
      if (trace) { log.trace("Reading"); }
     
      DataInputStream dis;
     
      if (in instanceof DataInputStream)
      {
         //For non HTTP transports - we should ALWAYS be passed a DataInputStream
         //We do this by specifying socket wrapper classes on the locator uri
         dis = (DataInputStream)in;        
        
         if (trace) { log.trace("Stream is already DataInputStream :)"); }
      }
      else
      {       
         // Further sanity check
         if (in instanceof ObjectInputStream)
         {
            throw new IllegalArgumentException("Invalid stream - are you sure you have " +
                                               "configured socket wrappers?");
         }
        
         // This would be the case for the HTTP transport for example. Wrap the stream
        
         //FIXME Ideally remoting would let us wrap this before invoking the marshaller
         //     but this does not appear to be possible
         dis = new DataInputStream(in);
        
         if (trace) { log.trace("Stream is NOT DataInputStream - must be using HTTP transport"); }
      }
     
      int id = dis.readInt();
     
      PacketSupport packet = PacketSupport.createPacket(id);
     
      if (trace) { log.trace("Created packet " + packet); }
     
      try
      {
         if (trace) { log.trace("Reading packet"); }
        
         packet.read(dis);
        
         if (trace) { log.trace("Read packet"); }
      }
      catch (Exception e)
      {
         IOException e2 = new IOException(e.getMessage());
         e2.setStackTrace(e.getStackTrace());
         throw e2;
      }
     
      Object payload = packet.getPayload();
     
      if (trace) { log.trace("Returning payload: " + payload); }
     
      return payload;
   }
     
   public UnMarshaller cloneUnMarshaller() throws CloneNotSupportedException
   {
      return this;
   }

   public void setClassLoader(ClassLoader classloader)
   {
   }

   // Public ---------------------------------------------------------------------------------------

   // Package protected ----------------------------------------------------------------------------

   // Protected ------------------------------------------------------------------------------------

   // Private --------------------------------------------------------------------------------------     

   // Inner classes --------------------------------------------------------------------------------
}
TOP

Related Classes of org.jboss.jms.server.remoting.JMSWireFormat

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.