Package com.googlecode.gwtrpccommlayer.server

Source Code of com.googlecode.gwtrpccommlayer.server.GwtRpcCommLayerServlet

/*
* Copyright 2010 Jeff McHugh (Segue Development LLC)
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.googlecode.gwtrpccommlayer.server;


import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.googlecode.gwtrpccommlayer.shared.GwtRpcCommLayerPojoConstants;
import com.googlecode.gwtrpccommlayer.shared.GwtRpcCommLayerPojoRequest;
import com.googlecode.gwtrpccommlayer.shared.GwtRpcCommLayerPojoResponse;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.LinkedList;

/**
* This class can either sit above your servlet (i.e. your servlet extends this) or it can wrap
* your servlet (i.e. it will receive the calls and delegate it to the respective methods
* @author jeff mchugh
*
*/
public class GwtRpcCommLayerServlet extends RemoteServiceServlet
{
 
  private static final long  serialVersionUID  = -8829760243946113688L;

  Object servletInstance = null;

    public GwtRpcCommLayerServlet() { }
    //@Inject
    //Can be extended and injected Guice
  public GwtRpcCommLayerServlet(Object servletImplementation)
  {
        this.servletInstance = servletImplementation;

        //this.servletImplementation = servletImplementation;
  }
 
  /**
   * Initializes the servlet
   */
  public void init(ServletConfig config) throws ServletException
  {
    super.init(config);
   
   
    /*
     * The default is to assume this instance is the selected servlet
     */
    servletInstance = this;
   
   
    /*
     * Check to see another servlet should be the target
     */
        //todo: this is currently configured using an init param in web.xml.  We need to change this to use something guice-friendly!
        //maybe use @Inject(optional=true) @Named("CommLayerImplClass") String strImplmentationClass;

    String servletImplClassName = config.getInitParameter(GwtRpcCommLayerPojoConstants.GWT_RPC_COMM_LAYER_SERVLET_IMPL_CLASS);
        //Use guice injected name instead of init parameter
        //if ( servletImplementation != null)
    if ( servletImplClassName != null && !servletImplClassName.trim().equals(""))
    {
      try
      {
        Class clzz = Class.forName(servletImplClassName);
        servletInstance = clzz.newInstance();
      }
      catch(Throwable t)
      {
        throw new ServletException(t);
      }
    }
  }
 
 
  /**
   * any servlet that extends can opt to deny these request
   * either explicitly or using web.xml
   * @return
   */
  protected boolean allowGwtRpcPojoRequest()
  {
    return true;
  }

  protected void initalizePerRequestPerResponseIfNeeded()
  {
    if ( super.perThreadRequest == null )
    {
      super.perThreadRequest = new ThreadLocal<HttpServletRequest>();
    }
    if ( super.perThreadResponse == null )
    {
      super.perThreadResponse = new ThreadLocal<HttpServletResponse>();
    }   
  }
 
 
  /**
   * Override the main service call and implement the special handling here
   */
  public void service(ServletRequest req, ServletResponse resp) throws ServletException, IOException
  {
   
    HttpServletRequest request     = (HttpServletRequest) req;
    HttpServletResponse response   = (HttpServletResponse) resp;
     
    /*
     * If the GwtRpcCommLayerClient has made this request, this header should be provided
     */
    String gwtClientUserAgent     = request.getHeader(GwtRpcCommLayerPojoConstants.GWT_RPC_COMM_LAYER_CLIENT_KEY);
     
   
    /*
     * Only execute this block if:
     *  - allowGwtRpcPojoRequest() is true
     *  - is POST
     *  - gwtClientUserAgent = 'GwtRpcCommLayerPojoRequest'
     */
    if ( allowGwtRpcPojoRequest()
                && request.getMethod().equals("POST")
                && gwtClientUserAgent != null
                && gwtClientUserAgent.equalsIgnoreCase(GwtRpcCommLayerPojoConstants.GWT_RPC_COMM_LAYER_POJO_CLIENT))
    {
      try
      {

        /*
         * This might not be initialized.
         * So do it if needed
         */
        initalizePerRequestPerResponseIfNeeded();
       
        super.perThreadRequest.set(request);
          super.perThreadResponse.set(response);
         
        doServicePojoRequest(request,response);
      }
      finally
      {
          super.perThreadRequest.set(null);
          super.perThreadResponse.set(null);       
      }
     
    }
    else
    {
      /*
       * Call up the chain and allow one of the implementations handle the request accordingly.
       * For an
       */
      super.service(req, resp);
    }
  }
 
  /**
   * Reads the request's InputStream and cast it to the correct Object type(s)
   * @param req
   * @param resp
   * @throws ServletException
   * @throws IOException
   */
  public void doServicePojoRequest(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
  {
    /*
     * The bytes that have been provided as the "POST" data
     * represent a serialized POJO
     *
     * read it and store it into a buffer (ByteArrayOutputStream)
     */
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    InputStream in = req.getInputStream();
    byte[] buff = new byte[1024];
    while(true)
    {
      int len = in.read(buff);
            //todo:is the ByteArrayOutputStream necessary? could just use: ObjectInputStream input = new ObjectInputStream(in);

      if ( len == -1 )
      {
        break;
      }
      bos.write(buff, 0, len);
    }
   
   
    if ( bos.toByteArray().length > 0 )
    {
      try
      {
        ObjectInputStream objIn = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
        Serializable ser = (Serializable) objIn.readObject();
        if ( ser instanceof GwtRpcCommLayerPojoRequest)
        {
          GwtRpcCommLayerPojoRequest rpcPojoReq = (GwtRpcCommLayerPojoRequest) ser;
          executePojoRequest(rpcPojoReq, req, resp);
        }
        else
        {
          throw new ServletException("POST data does not cast to an instance of GwtRpcCommLayerPojoRequest");
        }
      }
      catch(Throwable t)
      {
        throw new ServletException("Exception thrown executing pojo request.", t);
      }
    }
    else
    {
      throw new ServletException("POST data does not contain any serialized bytes.");
    }
   
  }
 
  /**
   * Execute the actual method within the GwtRpc servlet
   * @param pojoRequest
   * @param req
   * @param resp
   * @throws Throwable
   */
  public void executePojoRequest(GwtRpcCommLayerPojoRequest pojoRequest,HttpServletRequest req, HttpServletResponse resp) throws Throwable
  {
    try
    {
      /*
       * extract the appropriate method
       */
      Method method = getMethod(pojoRequest);
     
      /*
       * invoke the method
       */
      Object returnedInstance = invokeMethod(pojoRequest, method);
     
      /*
       * wrap response within a response object
       */
      GwtRpcCommLayerPojoResponse pojoResp = new GwtRpcCommLayerPojoResponse();
      pojoResp.setResponseInstance( (Serializable) returnedInstance);
     
      /*
       * send back the result as a stream set of bytes
       */
      serializeResponse(req,resp,pojoRequest,pojoResp);
    }
    catch(NoSuchMethodException e)
    {
      log("Method does not found.", e);
      resp.sendError(500, e.toString() );
    }
    catch(InvocationTargetException e)
    {
      log("Error executing method.", e.getCause());
      resp.sendError(500, e.toString() );
    }
    catch(IllegalAccessException e)
    {
      log("Error accessing method.", e);
      resp.sendError(500, e.toString() );
    }
  }
 
  /**
   * Write the appropriate response
   * @param req
   * @param resp
   * @param pojoRequest
   * @param pojoResp
   * @throws IOException
   */
  protected void serializeResponse(HttpServletRequest req, HttpServletResponse resp, GwtRpcCommLayerPojoRequest pojoRequest, GwtRpcCommLayerPojoResponse pojoResp) throws IOException
  {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream objOut = new ObjectOutputStream(bos);
    objOut.writeObject(pojoResp);
    objOut.flush();
    objOut.close();
   
    resp.setContentType("binary/octet-stream");
    resp.setContentLength(bos.toByteArray().length);
    OutputStream out = resp.getOutputStream();
    out.write(bos.toByteArray());
    out.flush();
  }
 
  /**
   *
   * @param stressTestRequest
   * @return
   * @throws NoSuchMethodException
   */
  protected Method getMethod(GwtRpcCommLayerPojoRequest stressTestRequest) throws NoSuchMethodException, ClassNotFoundException {
    int count = 0;
    Class<?> paramClasses[] = new Class[stressTestRequest.getMethodParameters().size()];

        LinkedList<Class<?>> lstParameterClasses = new LinkedList<Class<?>>();
        for (String className: stressTestRequest.getParameterClassNames()) {
            try {
              lstParameterClasses.add(Class.forName(className));
            } catch (ClassNotFoundException e) {
              if("long".equals(className)) {
                  lstParameterClasses.add(Long.TYPE);
              } else if("int".equals(className)) {
                    lstParameterClasses.add(Integer.TYPE);
              } else if("char".equals(className)) {
                    lstParameterClasses.add(Character.TYPE);
              } else if("double".equals(className)) {
                    lstParameterClasses.add(Double.TYPE);
              } else if("float".equals(className)) {
                    lstParameterClasses.add(Float.TYPE);
              } else if("byte".equals(className)) {
                    lstParameterClasses.add(Byte.TYPE);
              } else if("short".equals(className)) {
                    lstParameterClasses.add(Short.TYPE);
              } else {
                throw e;
              }
            }
        }

        Class[] arrParameterClasses = lstParameterClasses.toArray(new Class[0]);
        return servletInstance.getClass().getMethod(stressTestRequest.getMethodName(), arrParameterClasses);
    }
 
  /**
   *
   * @param stressTestRequest
   * @param method
   * @return
   * @throws InvocationTargetException
   * @throws IllegalAccessException
   */
  protected Object invokeMethod(GwtRpcCommLayerPojoRequest stressTestRequest, Method method) throws InvocationTargetException, IllegalAccessException
  {
        //todo: call toArray with correct size Object Array
    Object paramsAsObjects[] = stressTestRequest.getMethodParameters().toArray( new Object[0]);
    Object instance = method.invoke(servletInstance, paramsAsObjects);
    return instance;
  }
 
 
}
TOP

Related Classes of com.googlecode.gwtrpccommlayer.server.GwtRpcCommLayerServlet

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.