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