io.reinert.requestor.RequestDispatcherImpl.java Source code

Java tutorial

Introduction

Here is the source code for io.reinert.requestor.RequestDispatcherImpl.java

Source

/*
 * Copyright 2015 Danilo Reinert
 *
 * 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 io.reinert.requestor;

import javax.annotation.Nullable;

import com.google.gwt.core.client.JavaScriptException;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.xhr.client.ReadyStateChangeHandler;

import io.reinert.requestor.deferred.Deferred;
import io.reinert.requestor.header.Header;

/**
 * Default implementation of {@link RequestDispatcher}.
 *
 * @author Danilo Reinert
 */
public class RequestDispatcherImpl extends RequestDispatcher {

    public RequestDispatcherImpl(ResponseProcessor processor, DeferredFactory deferredFactory) {
        super(processor, deferredFactory);
    }

    @Override
    protected <D> void send(RequestOrder request, final Deferred<D> deferred, Class<D> resolveType,
            @Nullable Class<?> parametrizedType) {
        final HttpMethod httpMethod = request.getMethod();
        final String url = request.getUrl();
        final Headers headers = request.getHeaders();
        final Payload payload = request.getPayload();
        final ResponseType responseType = request.getResponseType();

        // Create XMLHttpRequest
        final XMLHttpRequest xmlHttpRequest = (XMLHttpRequest) XMLHttpRequest.create();

        // Open XMLHttpRequest
        try {
            xmlHttpRequest.open(httpMethod.getValue(), url);
        } catch (JavaScriptException e) {
            RequestPermissionException requestPermissionException = new RequestPermissionException(url);
            requestPermissionException.initCause(new RequestException(e.getMessage()));
            deferred.reject(requestPermissionException);
            return;
        }

        // Set withCredentials
        xmlHttpRequest.setWithCredentials(request.isWithCredentials());

        // Fulfill headers
        try {
            setHeaders(headers, xmlHttpRequest);
        } catch (JavaScriptException e) {
            deferred.reject(new RequestException("Could not manipulate the XHR headers: " + e.getMessage()));
            return;
        }

        // Set responseType
        xmlHttpRequest.setResponseType(responseType.getValue());

        // Create RequestCallback
        final RequestCallback callback = getRequestCallback(request, xmlHttpRequest, deferred, resolveType,
                parametrizedType);

        // Create the underlying request from gwt.http module
        final com.google.gwt.http.client.Request gwtRequest = new com.google.gwt.http.client.Request(xmlHttpRequest,
                request.getTimeout(), callback);

        // Properly configure XMLHttpRequest's onreadystatechange
        xmlHttpRequest.setOnReadyStateChange(new ReadyStateChangeHandler() {
            public void onReadyStateChange(com.google.gwt.xhr.client.XMLHttpRequest xhr) {
                if (xhr.getReadyState() == XMLHttpRequest.DONE) {
                    xhr.clearOnReadyStateChange();
                    ((XMLHttpRequest) xhr).clearOnProgress();
                    gwtRequest.fireOnResponseReceived(callback);
                }
            }
        });

        // Set XMLHttpRequest's onprogress if available binding to promise's progress
        xmlHttpRequest.setOnProgress(new ProgressHandler() {
            @Override
            public void onProgress(ProgressEvent progress) {
                deferred.notifyDownload(new RequestProgressImpl(progress));
            }
        });

        // Set XMLHttpRequest's upload onprogress if available binding to promise's progress
        xmlHttpRequest.setUploadOnProgress(new ProgressHandler() {
            @Override
            public void onProgress(ProgressEvent progress) {
                deferred.notifyUpload(new RequestProgressImpl(progress));
            }
        });

        // Pass the connection to the deferred to enable it to cancel the request if necessary (RECOMMENDED)
        deferred.setHttpConnection(getConnection(gwtRequest));

        // Send the request
        try {
            if (payload != null) {
                if (payload.isString() != null) {
                    xmlHttpRequest.send(payload.isString());
                } else {
                    xmlHttpRequest.send(payload.isJavaScriptObject());
                }
            } else {
                xmlHttpRequest.send();
            }
        } catch (JavaScriptException e) {
            deferred.reject(new RequestDispatchException("Could not send the XHR: " + e.getMessage()));
        }
    }

    private HttpConnection getConnection(final com.google.gwt.http.client.Request gwtRequest) {
        return new HttpConnection() {
            public void cancel() {
                gwtRequest.cancel();
            }

            public boolean isPending() {
                return gwtRequest.isPending();
            }
        };
    }

    private <D> RequestCallback getRequestCallback(final Request request, final XMLHttpRequest xhr,
            final Deferred<D> deferred, final Class<D> resolveType, final Class<?> parametrizedType) {
        return new RequestCallback() {
            public void onResponseReceived(com.google.gwt.http.client.Request gwtRequest,
                    com.google.gwt.http.client.Response gwtResponse) {
                final String responseType = xhr.getResponseType();

                final Payload payload = responseType.isEmpty() || responseType.equalsIgnoreCase("text")
                        ? new Payload(xhr.getResponseText())
                        : new Payload(xhr.getResponse());

                final RawResponseImpl response = new RawResponseImpl(gwtResponse.getStatusCode(),
                        gwtResponse.getStatusText(), new Headers(gwtResponse.getHeaders()),
                        ResponseType.of(responseType), payload);

                evalResponse(request, deferred, resolveType, parametrizedType, response);
            }

            public void onError(com.google.gwt.http.client.Request gwtRequest, Throwable exception) {
                if (exception instanceof com.google.gwt.http.client.RequestTimeoutException) {
                    // reject as timeout
                    com.google.gwt.http.client.RequestTimeoutException e = (com.google.gwt.http.client.RequestTimeoutException) exception;
                    deferred.reject(new RequestTimeoutException(request, e.getTimeoutMillis()));
                } else {
                    // reject as generic request exception
                    deferred.reject(new RequestException(exception));
                }
            }
        };
    }

    private void setHeaders(Headers headers, XMLHttpRequest xmlHttpRequest) throws JavaScriptException {
        if (headers != null && headers.size() > 0) {
            for (Header header : headers) {
                xmlHttpRequest.setRequestHeader(header.getName(), header.getValue());
            }
        }
    }
}