com.google.gwt.user.client.rpc.impl.RequestCallbackAdapter.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gwt.user.client.rpc.impl.RequestCallbackAdapter.java

Source

/*
 * Copyright 2008 Google Inc.
 * 
 * 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.google.gwt.user.client.rpc.impl;

import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.Response;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException;
import com.google.gwt.user.client.rpc.InvocationException;
import com.google.gwt.user.client.rpc.RpcTokenException;
import com.google.gwt.user.client.rpc.RpcTokenExceptionHandler;
import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.client.rpc.SerializationStreamFactory;
import com.google.gwt.user.client.rpc.SerializationStreamReader;
import com.google.gwt.user.client.rpc.StatusCodeException;

/**
 * Adapter from a {@link RequestCallback} interface to an {@link AsyncCallback}
 * interface.
 * 
 * For internal use only.
 * 
 * @param <T>
 *            the type parameter for the {@link AsyncCallback}
 */
public class RequestCallbackAdapter<T> implements RequestCallback {
    /**
     * {@link AsyncCallback} to notify or success or failure.
     */
    private final AsyncCallback<T> callback;

    /**
     * Used for stats recording.
     */
    private final String methodName;

    /**
     * Used for stats recording.
     */
    private final RpcStatsContext statsContext;

    /**
     * Instance which will read the expected return type out of the
     * {@link SerializationStreamReader}.
     */
    private final ResponseReader responseReader;

    /**
     * {@link RpcTokenExceptionHandler} to notify of token exceptions.
     */
    private final RpcTokenExceptionHandler tokenExceptionHandler;

    /**
     * {@link SerializationStreamFactory} for creating
     * {@link SerializationStreamReader}s.
     */
    private final SerializationStreamFactory streamFactory;

    public RequestCallbackAdapter(SerializationStreamFactory streamFactory, String methodName,
            RpcStatsContext statsContext, AsyncCallback<T> callback, ResponseReader responseReader) {
        this(streamFactory, methodName, statsContext, callback, null, responseReader);
    }

    public RequestCallbackAdapter(SerializationStreamFactory streamFactory, String methodName,
            RpcStatsContext statsContext, AsyncCallback<T> callback, RpcTokenExceptionHandler tokenExceptionHandler,
            ResponseReader responseReader) {
        assert (streamFactory != null);
        assert (callback != null);
        assert (responseReader != null);
        this.streamFactory = streamFactory;
        this.callback = callback;
        this.methodName = methodName;
        this.statsContext = statsContext;
        this.responseReader = responseReader;
        this.tokenExceptionHandler = tokenExceptionHandler;
    }

    public void onError(Request request, Throwable exception) {
        callback.onFailure(exception);
    }

    @SuppressWarnings(value = { "unchecked" })
    public void onResponseReceived(Request request, Response response) {
        T result = null;
        Throwable caught = null;
        final PostDeserializationCallback postDeserializationCallback = new PostDeserializationCallback();
        try {
            String encodedResponse = response.getText();
            int statusCode = response.getStatusCode();
            boolean toss = statsContext.isStatsAvailable() && statsContext
                    .stats(statsContext.bytesStat(methodName, encodedResponse.length(), "responseReceived"));
            if (statusCode != Response.SC_OK) {
                caught = new StatusCodeException(statusCode, encodedResponse);
            } else if (encodedResponse == null) {
                // This can happen if the XHR is interrupted by the server dying
                caught = new InvocationException("No response payload from " + methodName);
            } else if (RemoteServiceProxy.isThrownException(encodedResponse)) {
                final ClientSerializationStreamReader exceptionReader = (ClientSerializationStreamReader) streamFactory
                        .createStreamReader(encodedResponse);
                postDeserializationCallback.streamReader = exceptionReader;
                AsyncCallback exceptionCallback = new AsyncCallback() {
                    @Override
                    public void onFailure(Throwable caught) {
                        postDeserializationCallback.onFailure(caught);
                    }

                    @Override
                    public void onSuccess(Object toss) {
                        try {
                            Object object = exceptionReader.readObject();
                            onFailure((Throwable) object);
                        } catch (Throwable e) {
                            onFailure(e);
                        }
                    }
                };
                exceptionReader.doDeserialize(exceptionCallback);
                return;
            } else if (RemoteServiceProxy.isReturnValue(encodedResponse)) {
                // next clause
            } else {
                caught = new InvocationException(encodedResponse + " from " + methodName);
            }
            if (caught != null) {
            } else {
                if (RemoteServiceProxy.isReturnValue(encodedResponse)) {
                    ClientSerializationStreamReader reader = (ClientSerializationStreamReader) streamFactory
                            .createStreamReader(encodedResponse);
                    postDeserializationCallback.streamReader = reader;
                    reader.doDeserialize(postDeserializationCallback);
                    return;
                }
            }
        } catch (com.google.gwt.user.client.rpc.SerializationException e) {
            caught = new IncompatibleRemoteServiceException("The response could not be deserialized", e);
        } catch (Throwable e) {
            caught = e;
        }
        if (caught != null) {
            postDeserializationCallback.onFailure(caught);
        } else {
            postDeserializationCallback.onSuccess(null);
        }
    }

    /**
     * Enumeration used to read specific return types out of a
     * {@link SerializationStreamReader}.
     */
    public enum ResponseReader {
        BOOLEAN {
            @Override
            public Object read(SerializationStreamReader streamReader) throws SerializationException {
                return streamReader.readBoolean();
            }
        },
        BYTE {
            @Override
            public Object read(SerializationStreamReader streamReader) throws SerializationException {
                return streamReader.readByte();
            }
        },
        CHAR {
            @Override
            public Object read(SerializationStreamReader streamReader) throws SerializationException {
                return streamReader.readChar();
            }
        },
        DOUBLE {
            @Override
            public Object read(SerializationStreamReader streamReader) throws SerializationException {
                return streamReader.readDouble();
            }
        },
        FLOAT {
            @Override
            public Object read(SerializationStreamReader streamReader) throws SerializationException {
                return streamReader.readFloat();
            }
        },
        INT {
            @Override
            public Object read(SerializationStreamReader streamReader) throws SerializationException {
                return streamReader.readInt();
            }
        },
        LONG {
            @Override
            public Object read(SerializationStreamReader streamReader) throws SerializationException {
                return streamReader.readLong();
            }
        },
        OBJECT {
            @Override
            public Object read(SerializationStreamReader streamReader) throws SerializationException {
                return streamReader.readObject();
            }
        },
        SHORT {
            @Override
            public Object read(SerializationStreamReader streamReader) throws SerializationException {
                return streamReader.readShort();
            }
        },
        STRING {
            @Override
            public Object read(SerializationStreamReader streamReader) throws SerializationException {
                return streamReader.readString();
            }
        },
        VOID {
            @Override
            public Object read(SerializationStreamReader streamReader) {
                return null;
            }
        };
        public abstract Object read(SerializationStreamReader streamReader) throws SerializationException;
    }

    class PostDeserializationCallback implements AsyncCallback {
        public ClientSerializationStreamReader streamReader;

        private Object result;

        private Throwable caught;

        public PostDeserializationCallback() {
        }

        @Override
        public void onFailure(Throwable caught) {
            this.caught = caught;
            postDeserializeStats();
            if (tokenExceptionHandler != null && caught instanceof RpcTokenException) {
                tokenExceptionHandler.onRpcTokenException((RpcTokenException) caught);
            } else {
                callback.onFailure(caught);
            }
            postCallbackStats();
        }

        @Override
        public void onSuccess(Object toss) {
            result = null;
            if (streamReader != null) {
                try {
                    result = (T) responseReader.read(streamReader);
                } catch (Throwable e) {
                    onFailure(e);
                }
            }
            postDeserializeStats();
            try {
                callback.onSuccess((T) result);
            } finally {
                postCallbackStats();
            }
        }

        private void postCallbackStats() {
            Object returned = (caught == null) ? result : caught;
            boolean toss = statsContext.isStatsAvailable()
                    && statsContext.stats(statsContext.timeStat(methodName, returned, "end"));
        }

        private void postDeserializeStats() {
            boolean toss = statsContext.isStatsAvailable()
                    && statsContext.stats(statsContext.timeStat(methodName, "responseDeserialized"));
        }
    }
}