@Override public String processCall(String payload) throws SerializationException { try { perThreadRequest.set(getThreadLocalRequest()); Object handler = getBean(getThreadLocalRequest()); RPCRequest rpcRequest = RPC.decodeRequest(payload, handler.getClass(), this); onAfterRequestDeserialized(rpcRequest); if (LOG.isDebugEnabled()) { LOG.debug("Invoking " + handler.getClass().getName() + "." + rpcRequest.getMethod().getName()); } return RpcHelper .invokeAndEncodeResponse( handler, rpcRequest.getMethod(), rpcRequest.getParameters(), rpcRequest.getSerializationPolicy() ); } catch (IncompatibleRemoteServiceException ex) { log("An IncompatibleRemoteServiceException was thrown while processing this call.", ex); return RPC.encodeResponseForFailure(null, ex); } catch (SerializationException ex) { LOG.error("An SerializationException was thrown while processing this call.", ex); throw ex; } finally { perThreadRequest.set(null); } }
Object result = serviceMethod.invoke(target, args); responsePayload = RPC.encodeResponseForSuccess(serviceMethod, result, serializationPolicy, flags); .encodeResponseForFailure(serviceMethod, cause, serializationPolicy, flags);
private void writeResponse(HttpServletRequest request, HttpServletResponse response, String responsePayload) throws IOException { boolean gzipEncode = RPCServletUtils.acceptsGzipEncoding(request) && shouldCompressResponse(request, response, responsePayload); RPCServletUtils.writeResponse(getServletContext(), response, responsePayload, gzipEncode); } }
@Override protected void onAfterRequestDeserialized(RPCRequest rpcRequest) { if (shouldValidateXsrfToken(rpcRequest.getMethod())) { validateXsrfToken(rpcRequest.getRpcToken(), rpcRequest.getMethod()); } }
/** * Returns a string that encodes the object. It is an error to try to encode * an object that is not assignable to the service method's return type. * * @param serviceMethod the method whose result we are encoding * @param object the instance that we wish to encode * @return a string that encodes the object, if the object is compatible with * the service method's declared return type * * @throws IllegalArgumentException if the result is not assignable to the * service method's return type * @throws NullPointerException if the service method is <code>null</code> * @throws SerializationException if the result cannot be serialized */ public static String encodeResponseForSuccess(Method serviceMethod, Object object) throws SerializationException { return encodeResponseForSuccess(serviceMethod, object, getDefaultSerializationPolicy()); }
/** * Returns <code>true</code> if the request accepts gzip encoding and the * response content's estimated UTF-8 byte length exceeds 256 bytes. * * @param request the request associated with the response content * @param responseContent a string that will be * @return <code>true</code> if the request accepts gzip encoding and the * response content's estimated UTF-8 byte length exceeds 256 bytes */ public static boolean shouldGzipResponseContent(HttpServletRequest request, String responseContent) { return acceptsGzipEncoding(request) && exceedsUncompressedContentLengthLimit(responseContent); }
public static String encodeResponseForFailure(Method serviceMethod, Throwable cause, SerializationPolicy serializationPolicy, int flags) throws SerializationException { if (cause == null) { throw new NullPointerException("cause cannot be null"); } if (serializationPolicy == null) { throw new NullPointerException("serializationPolicy"); } if (serviceMethod != null && !RPCServletUtils.isExpectedException(serviceMethod, cause)) { throw new UnexpectedException("Service method '" + getSourceRepresentation(serviceMethod) + "' threw an unexpected exception: " + cause.toString(), cause); } return encodeResponse(cause.getClass(), cause, true, flags, serializationPolicy); }
/** * Server-side deserialize does not match server-side serialize, so we can't test a round trip. */ public static <T> void gwtSerialize(T object) throws SerializationException { RPC.encodeResponseForSuccess(arbitraryVoidReturningMethod(), object); }
/** * Overridden to load the gwt.codeserver.port system property. */ @Override public void init(ServletConfig config) throws ServletException { super.init(config); codeServerPort = getCodeServerPort(); }
/** * Returns the content of an {@link HttpServletRequest}, after verifying a * <code>gwt/x-gwt-rpc; charset=utf-8</code> content type. * * @param request the servlet request whose content we want to read * @return the content of an {@link HttpServletRequest} by decoding it using * <code>UTF-8</code> * @throws IOException if the request's input stream cannot be accessed, read * from or closed * @throws ServletException if the request's content type is not * <code>gwt/x-gwt-rpc; charset=utf-8</code>, ignoring case */ public static String readContentAsGwtRpc(HttpServletRequest request) throws IOException, ServletException { return readContent(request, GWT_RPC_CONTENT_TYPE, CHARSET_UTF8_NAME); }
/** * Returns the fields of a particular class that can be considered for * serialization. The returned list will be sorted into a canonical order to * ensure consistent answers. */ public static Field[] applyFieldSerializationPolicy(Class<?> clazz, SerializationPolicy policy) { return applyFieldSerializationPolicy(clazz, policy.shouldSerializeFinalFields()); }
/** * Override this method in order to control the parsing of the incoming * request. For example, you may want to bypass the check of the Content-Type * and character encoding headers in the request, as some proxies re-write the * request headers. Note that bypassing these checks may expose the servlet to * some cross-site vulnerabilities. Your implementation should comply with the * HTTP/1.1 specification, which includes handling both requests which include * a Content-Length header and requests utilizing <code>Transfer-Encoding: * chuncked</code>. * * @param request the incoming request * @return the content of the incoming request encoded as a string. */ protected String readContent(HttpServletRequest request) throws ServletException, IOException { return RPCServletUtils.readContentAsGwtRpc(request); }
@Override public void logError(String message, Throwable throwable) { RemoteServiceServlet.this.log(message, throwable); } };
/** * Gets the <code>HttpServletResponse</code> object for the current call. It * is stored thread-locally so that simultaneous invocations can have * different response objects. */ protected final HttpServletResponse getThreadLocalResponse() { synchronized (this) { validateThreadLocalData(); return perThreadResponse.get(); } }
/** * XSRF protected equivalent of {@link RemoteService}. * All calls on RPC interfaces extending this interface will be XSRF protected. */ @XsrfProtect public interface XsrfProtectedService extends RemoteService { }
/** * Returns the strong name of the permutation, as reported by the client that * issued the request, or <code>null</code> if it could not be determined. * This information is encoded in the * {@value com.google.gwt.user.client.rpc.RpcRequestBuilder#STRONG_NAME_HEADER} * HTTP header. */ protected final String getPermutationStrongName() { return getThreadLocalRequest().getHeader(STRONG_NAME_HEADER); }
/** * Servlet initialization. */ @Override public void init() { // do not overwrite values set via constructor if (sessionCookieName == null) { sessionCookieName = getInitParameterValue(COOKIE_NAME_PARAM); } if (sessionCookieName == null) { throw new IllegalStateException(COOKIE_NAME_NOT_SET_ERROR_MSG); } }
/** * Generates and returns new XSRF token. */ public XsrfToken getNewXsrfToken() { return new XsrfToken(generateTokenValue()); }
@Override public void logInfo(String message) { RemoteServiceServlet.this.log(message); }
/** * Gets the <code>HttpServletRequest</code> object for the current call. It is * stored thread-locally so that simultaneous invocations can have different * request objects. */ protected final HttpServletRequest getThreadLocalRequest() { synchronized (this) { validateThreadLocalData(); return perThreadRequest.get(); } }