All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.cinchapi.concourse.server.plugin.RemoteMethodResponse Maven / Gradle / Ivy

/*
 * Copyright (c) 2013-2017 Cinchapi 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.cinchapi.concourse.server.plugin;

import io.atomix.catalyst.buffer.Buffer;

import java.nio.ByteBuffer;
import java.util.Map;
import java.util.Objects;

import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;

import com.cinchapi.concourse.annotate.PackagePrivate;
import com.cinchapi.concourse.thrift.AccessToken;
import com.cinchapi.concourse.thrift.ComplexTObject;
import com.google.common.collect.Maps;

/**
 * A message that is sent from one process to another via a
 * {@link InterProcessCommunication} segment with the result of a
 * {@link RemoteMethodRequest}.
 * 
 * @author Jeff Nelson
 */
@Immutable
@PackagePrivate
final class RemoteMethodResponse extends RemoteMessage {

    /**
     * The {@link AccessToken} of the session for which the response is routed.
     */
    public AccessToken creds;

    /**
     * The error that was thrown.
     */
    @Nullable
    public Exception error;

    /**
     * The response encapsulated as a thrift serializable object.
     */
    @Nullable
    public ComplexTObject response;

    /**
     * Construct a new instance.
     * 
     * @param creds
     * @param response
     */
    public RemoteMethodResponse(AccessToken creds, ComplexTObject response) {
        this.creds = creds;
        this.response = response;
        this.error = null;
    }

    /**
     * Construct a new instance.
     * 
     * @param creds
     * @param error
     */
    public RemoteMethodResponse(AccessToken creds, Exception error) {
        this.creds = creds;
        this.response = null;
        this.error = error;
    }

    /**
     * DO NOT CALL. Only here for deserialization.
     */
    RemoteMethodResponse() {/* no-op */}

    @Override
    public void deserialize(Buffer buffer) {
        boolean isError = buffer.readBoolean();
        int credsLength = buffer.readInt();
        byte[] creds = new byte[credsLength];
        buffer.read(creds);
        this.creds = new AccessToken(ByteBuffer.wrap(creds));
        if(isError) {
            this.error = new RuntimeException(buffer.readUTF8());
        }
        else {
            byte[] response = new byte[(int) buffer.remaining()];
            buffer.read(response);
            this.response = ComplexTObject
                    .fromByteBuffer(ByteBuffer.wrap(response));
        }
    }

    @Override
    public boolean equals(Object obj) {
        if(obj instanceof RemoteMethodResponse) {
            return Objects.equals(creds, ((RemoteMethodResponse) obj).creds)
                    && error == null
                            ? Objects.equals(response,
                                    ((RemoteMethodResponse) obj).response)
                            : Objects.equals(error,
                                    ((RemoteMethodResponse) obj).error);
        }
        else {
            return false;
        }
    }

    @Override
    public int hashCode() {
        return Objects.hash(creds, error == null ? response : error);
    }

    /**
     * Return {@code true} if this {@link RemoteMethodResponse response}
     * indicates an error.
     * 
     * @return {@code true} if this is an error response
     */
    public boolean isError() {
        return error != null;
    }

    @Override
    public String toString() {
        Map data = Maps.newHashMap();
        data.put("error", isError());
        data.put("response", isError() ? error : response);
        data.put("creds", creds);
        return data.toString();
    }

    @Override
    public Type type() {
        return Type.RESPONSE;
    }

    @Override
    protected void serialize(Buffer buffer) {
        buffer.writeBoolean(isError());
        byte[] creds = this.creds.getData();
        buffer.writeInt(creds.length);
        buffer.write(creds);
        if(isError()) {
            buffer.writeUTF8(error.getMessage());
        }
        else {
            buffer.write(response.toByteBuffer().array());
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy