Package org.pentaho.platform.web.servlet

Source Code of org.pentaho.platform.web.servlet.AbstractGwtRpcProxyServlet

/*!
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program 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.
*
* Copyright (c) 2002-2013 Pentaho Corporation..  All rights reserved.
*/

package org.pentaho.platform.web.servlet;

import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException;
import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.server.rpc.RPC;
import com.google.gwt.user.server.rpc.RPCRequest;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.google.gwt.user.server.rpc.impl.StandardSerializationPolicy;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.pentaho.platform.web.servlet.messages.Messages;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

@SuppressWarnings( "serial" )
/**
* Base class for GWT RPC proxying servlets, which allows developers to write GWT Services as Pojos and have
* the GWT client POST requests to subclasses of this class.
*/
public abstract class AbstractGwtRpcProxyServlet extends RemoteServiceServlet {

  private static final Log logger = LogFactory.getLog( AbstractGwtRpcProxyServlet.class );

  public AbstractGwtRpcProxyServlet() {
    super();
  }

  /**
   * Resolve the target impl that ultimately handles the GWT RPC request, provided a key.
   *
   * @param servletContextPath
   *          the portion of the http request path beyond the servlet context, used to uniquely identify the target impl
   * @return the object that handles the request
   * @throws GwtRpcProxyException
   *           if no target can be found
   */
  protected abstract Object resolveDispatchTarget( String servletContextPath );

  protected void doUnexpectedFailure( Throwable e ) {
    super.doUnexpectedFailure( e );
    logger.error( e );
  }

  /**
   * Returns the dispatch key for this request. This name is the part of the request path beyond the servlet base path.
   * I.e. if the GwtRpcPluginProxyServlet is mapped to the "/gwtrpc" context in web.xml, then this method will return
   * "testservice" upon a request to "http://localhost:8080/pentaho/gwtrpc/testservice".
   *
   * @return the part of the request url used to dispatch the request
   */
  protected String getDispatchKey() {
    HttpServletRequest request = getThreadLocalRequest();
    // path info will give us what we want with
    String requestPathInfo = request.getPathInfo();
    if ( requestPathInfo.startsWith( "/" ) ) { //$NON-NLS-1$
      requestPathInfo = requestPathInfo.substring( 1 );
    }
    if ( requestPathInfo.contains( "/" ) ) { //$NON-NLS-1$
      // if the request path happens to be multiple levels deep, return the last element in the path
      String[] elements = requestPathInfo.split( "/" ); //$NON-NLS-1$
      return elements[elements.length - 1];
    }
    return requestPathInfo;
  }

  @SuppressWarnings( "nls" )
  protected String getServletContextPath() {
    HttpServletRequest request = getThreadLocalRequest();
    String path = request.getServletPath() + "/" + request.getPathInfo();
    if ( path.contains( "//" ) ) {
      path = path.replaceAll( "//", "/" );
    }
    return path;
  }

  @Override
  public String processCall( String payload ) throws SerializationException {
    Map<Class<?>, Boolean> whitelist = new HashMap<Class<?>, Boolean>();
    whitelist.put( GwtRpcProxyException.class, Boolean.TRUE );
    Map<Class<?>, String> obfuscatedTypeIds = new HashMap<Class<?>, String>();
    StandardSerializationPolicy policy = new StandardSerializationPolicy( whitelist, whitelist, obfuscatedTypeIds );

    String servletContextPath = getServletContextPath();

    Object target = null;
    try {
      target = resolveDispatchTarget( servletContextPath );
    } catch ( GwtRpcProxyException ex ) {
      logger.error( Messages.getInstance().getErrorString(
          "AbstractGwtRpcProxyServlet.ERROR_0001_FAILED_TO_RESOLVE_DISPATCH_TARGET", servletContextPath ), ex ); //$NON-NLS-1$
      return RPC.encodeResponseForFailure( null, ex, policy );
    }

    final ClassLoader origLoader = Thread.currentThread().getContextClassLoader();
    final ClassLoader altLoader = target.getClass().getClassLoader();

    try {
      // temporarily swap out the context classloader to an alternate classloader if
      // the targetBean has been loaded by one other than the context classloader.
      // This is necessary, so the RPC class can do a Class.forName and find the service
      // class specified in the request
      if ( altLoader != origLoader ) {
        Thread.currentThread().setContextClassLoader( altLoader );
      }

      RPCRequest rpcRequest = RPC.decodeRequest( payload, null, this );
      onAfterRequestDeserialized( rpcRequest );
      // don't require the server side to implement the service interface
      Method method = rpcRequest.getMethod();
      try {
        Method m = target.getClass().getMethod( method.getName(), method.getParameterTypes() );
        if ( m != null ) {
          method = m;
        }
      } catch ( Exception e ) {
        e.printStackTrace();
      }
      return RPC.invokeAndEncodeResponse( target, method, rpcRequest.getParameters(), rpcRequest
          .getSerializationPolicy() );
    } catch ( IncompatibleRemoteServiceException ex ) {
      logger.error( Messages.getInstance().getErrorString(
          "AbstractGwtRpcProxyServlet.ERROR_0003_RPC_INVOCATION_FAILED", target.getClass().getName() ), ex ); //$NON-NLS-1$
      return RPC.encodeResponseForFailure( null, ex );
    } finally {
      // reset the context classloader if necessary
      if ( ( altLoader != origLoader ) && origLoader != null ) {
        Thread.currentThread().setContextClassLoader( origLoader );
      }
    }
  }
}
TOP

Related Classes of org.pentaho.platform.web.servlet.AbstractGwtRpcProxyServlet

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.