[rules-users] workaround: guvnor repository remote commands using http (bypassing gwt interface)

Wesley Akio Imamura wesley.imamura at gmail.com
Fri Oct 23 15:02:31 EDT 2009


workaround: guvnor repository remote commands using http (bypassing
gwt interface)

the commands are passed using serialized java objects.

IN web.xml:

   <servlet>
      <servlet-name>XptoServlet</servlet-name>
      <servlet-class>org.jboss.seam.remoting.gwt.AcecServlet</servlet-class>
   </servlet>

   <servlet-mapping>
      <servlet-name>XptoServlet</servlet-name>
      <url-pattern>/AcecServlet</url-pattern>
   </servlet-mapping>

Servlet code:

package org.jboss.seam.remoting.gwt;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.drools.guvnor.client.rpc.DetailedSerializableException;
import org.drools.guvnor.client.rpc.RepositoryService;
import org.drools.guvnor.client.rpc.SecurityService;
import org.drools.guvnor.client.rpc.SessionExpiredException;
import org.jboss.seam.Component;
import org.jboss.seam.annotations.remoting.WebRemote;
import com.google.gwt.user.client.rpc.SerializationException;
import org.drools.guvnor.server.security.SecurityServiceImpl;
/**
 *
 * @author Wesley Imamura
 */
public class XptoServlet extends HttpServlet {
  private static final String GENERIC_FAILURE_MSG = "An error occurred
on the server. Consult server log for details.";
  private static final HashMap TYPE_NAMES;
  static final Map METHOD_CACHE = new HashMap();
  static {
       TYPE_NAMES = new HashMap();
       TYPE_NAMES.put("Z", boolean.class);
       TYPE_NAMES.put("B", byte.class);
       TYPE_NAMES.put("C", char.class);
       TYPE_NAMES.put("D", double.class);
       TYPE_NAMES.put("F", float.class);
       TYPE_NAMES.put("I", int.class);
       TYPE_NAMES.put("J", long.class);
       TYPE_NAMES.put("S", short.class);
     }
  public final void doPost(HttpServletRequest request,
HttpServletResponse response) {
   Throwable caught;
    try {

       System.out.println("Reading map.");
       ObjectInputStream ois = new ObjectInputStream(request.getInputStream());
       Map map = (Map) ois.readObject();
       ois.close();
       System.out.println("Map read.");
       String methodName = (String) map.get("methodName");
       System.out.println("methodName: " + methodName);

       Integer paramCount = (Integer) map.get("paramCount");
       System.out.println("paramCount: " + paramCount.intValue());

        Class[] paramTypes = new Class[paramCount];
        for (int i = 0; i < paramCount; i++) {
          String paramClassName = (String) map.get("param" + i + "Type");
          System.out.println("paramClassName: " + paramClassName);
          try {
            paramTypes[i] = getClassOrPrimitiveFromName(paramClassName);
          } catch (ClassNotFoundException e) {
            throw new SerializationException("Unknown parameter " + i
+ " type '"
                + paramClassName + "'", e);
          }
        }

        Object[] args = new Object[paramCount];
        for (int i = 0; i < args.length; i++) {
          args[i] = map.get("param" + i + "Value");
          if (args[i] != null) {
             if (args[i].getClass().getName().equals("java.lang.String"))

System.out.println("GWTRemoteServiceServlet.processCall(). args[" + i
+ "]: " + ((String) args[i]));
             else

System.out.println("GWTRemoteServiceServlet.processCall(). args[" + i
+ "]: " + args[i].toString());
          }
        }
        System.out.println("args ok.");
        RepositoryService repositoryService = (RepositoryService)
Component.getInstance("org.drools.guvnor.client.rpc.RepositoryService");
        System.out.println("repositoryService ok.");
        Method method = getMethod(
"org.drools.guvnor.client.rpc.RepositoryService", methodName,
repositoryService.getClass(), paramTypes );
        System.out.println("method ok.");
        try {
           SecurityService securityService = new
SecurityServiceImpl(); // (SecurityService)
Component.getInstance("org.drools.guvnor.client.rpc.SecurityService");
           boolean isLogged = securityService.login("admin", "password");
           System.out.println("logged in.");

           System.out.println("invoking.");
           Object result = method.invoke( repositoryService, args );
           System.out.println("invoked.");

           ReturnedObject returnedObject = new
ReturnedObject(method.getReturnType(), result);

           System.out.println("writing response.");
           ObjectOutputStream oos = new
ObjectOutputStream(response.getOutputStream());
           oos.writeObject(returnedObject);
           oos.close();
           System.out.println("response wrote.");

        } catch (InvocationTargetException e) {
           //now in this case, we log, and then repack it as some sort
of a serializable exception
           String exName = e.getCause().getClass().getName();
           if (exName.endsWith( "NotLoggedInException" )) {
              throw new InvocationTargetException(new
SessionExpiredException());
           } else {
              Throwable cause = e.getCause();
              StringWriter sw = new StringWriter();
              PrintWriter w = new PrintWriter(sw);
              cause.printStackTrace( w );
              DetailedSerializableException det = new
DetailedSerializableException("An error occurred executing the
action.", sw.toString());
              throw new InvocationTargetException(det);
           }
        }

        response.setContentType("application/binary");
        response.setStatus(HttpServletResponse.SC_OK);
        return;
    } catch (Throwable e) {

       e.printStackTrace();

      caught = e;
      respondWithFailure(response, caught);
    }

  }
  /**
   * Called when the machinery of this class itself has a problem, rather than
   * the invoked third-party method. It writes a simple 500 message back to the
   * client.
   */
  private void respondWithFailure(HttpServletResponse response,
Throwable caught) {
    ServletContext servletContext = getServletContext();
    servletContext.log("Exception while dispatching incoming RPC call", caught);
    try {
      response.setContentType("text/plain");
      response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
      response.getWriter().write(GENERIC_FAILURE_MSG);
    } catch (IOException e) {
      servletContext.log(
          "sendError() failed while sending the previous failure to the client",
          caught);
    }
  }

  private Class getClassOrPrimitiveFromName(String name) throws
ClassNotFoundException {
     Object value = TYPE_NAMES.get(name);
     if (value != null) {
        return (Class) value;
     }
     return getClassFromName(name);
  }
  private Class getClassFromName(String name) throws ClassNotFoundException {
       return Class.forName(name, false, this.getClass().getClassLoader());
  }

  private Method getMethod(String serviceName, String methodName,
Class clz, Class[] paramTypes)  {
     String key = getKey( serviceName,  methodName, paramTypes );
     if (METHOD_CACHE.containsKey( key )) {
        return (Method) METHOD_CACHE.get( key );
     } else {
        try {
           synchronized ( METHOD_CACHE ) {
              Method m = findMethod( clz, methodName, paramTypes );
              if (m == null) throw new NoSuchMethodException();
              METHOD_CACHE.put( key, m );
              return m;
           }
        } catch ( NoSuchMethodException e ) {
           throw new SecurityException("Unable to access a service
method called [" + methodName + "] on class [" + clz.getName() + "]
without the @WebRemote attribute. " +
            "This may be a hack attempt, or someone simply neglected
to use the @WebRemote attribute to indicate a method as" +
              " remotely accessible.");
        }
     }
  }

  private String getKey(String serviceName, String methodName, Class[]
paramTypes) {
     if (paramTypes == null) {
        return serviceName + "." + methodName;
     } else {
        String pTypes = "";
        for ( int i = 0; i < paramTypes.length; i++ ) {
           pTypes += paramTypes[i].getName();
        }
        return serviceName + "." + methodName + "(" + pTypes + ")";
     }
  }
  private Method findMethod(Class clz, String methodName, Class[]
paramTypes ) throws NoSuchMethodException {
     if (clz == Object.class) {
        return null;
     } else {
        Method m = clz.getMethod( methodName, paramTypes );
        if (isWebRemoteAnnotated( m )) {
           return m;
        } else {
           return findMethod(clz.getSuperclass(), methodName, paramTypes);
        }
     }
  }
  private boolean isWebRemoteAnnotated(Method method) {
      if (method == null) return false;
      return method.getAnnotation( WebRemote.class ) != null;
  }
  public static class ReturnedObject implements Serializable {
      public ReturnedObject(Class type,
                            Object result) {
          this.returnType = type;
          this.returnedObject = result;
      }
      public Class returnType;
      public Object returnedObject;
  }
}



-- 
Wesley Akio Imamura
São Paulo - SP - Brazil
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/rules-users/attachments/20091023/3057d732/attachment.html 


More information about the rules-users mailing list