Merge "Use String(byte[], Charset)"
[openflowplugin.git] / openflowjava / openflow-protocol-impl / src / main / java / org / opendaylight / openflowjava / protocol / impl / core / connection / AbstractRpcListener.java
1 /*
2  * Copyright (c) 2014 Pantheon Technologies s.r.o. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.openflowjava.protocol.impl.core.connection;
9
10 import static com.google.common.base.Preconditions.checkState;
11 import static java.util.Objects.requireNonNull;
12
13 import com.google.common.util.concurrent.ListenableFuture;
14 import com.google.common.util.concurrent.SettableFuture;
15 import io.netty.util.concurrent.Future;
16 import io.netty.util.concurrent.GenericFutureListener;
17 import org.opendaylight.yangtools.yang.common.RpcError;
18 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
19 import org.opendaylight.yangtools.yang.common.RpcResult;
20 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 /**
25  * This class holds all the context we need for sending a single message down the tube.
26  * A MessageHolder (used in queue) and the actual listener. It is not a thing of beauty,
27  * but it keeps us from allocating unnecessary objects in the egress path.
28  */
29 abstract class AbstractRpcListener<T> implements GenericFutureListener<Future<Void>>,
30         ChannelOutboundQueue.MessageHolder<Object> {
31     private static final Logger LOG = LoggerFactory.getLogger(AbstractRpcListener.class);
32     private static final String APPLICATION_TAG = "OPENFLOW_LIBRARY";
33     private static final String TAG = "OPENFLOW";
34     private final SettableFuture<RpcResult<T>> result = SettableFuture.create();
35     private final String failureInfo;
36     private Object message;
37
38     /**
39      * Create RcpError object.
40      *
41      * @param info error info
42      * @param message error message
43      * @param cause - details of reason
44      * @return RpcError
45      */
46     static RpcError buildRpcError(final String info, final String message, final Throwable cause) {
47         return RpcResultBuilder.newError(ErrorType.RPC, TAG, message, APPLICATION_TAG, info, cause);
48     }
49
50     AbstractRpcListener(final Object message, final String failureInfo) {
51         this.failureInfo = requireNonNull(failureInfo);
52         this.message = requireNonNull(message);
53     }
54
55     public final ListenableFuture<RpcResult<T>> getResult() {
56         return result;
57     }
58
59     @Override
60     public final void operationComplete(final Future<Void> future) {
61         if (!future.isSuccess()) {
62             LOG.debug("operation failed");
63             failedRpc(future.cause());
64         } else {
65             LOG.debug("operation complete");
66             operationSuccessful();
67         }
68     }
69
70     @Override
71     public final Object takeMessage() {
72         final Object ret = message;
73         checkState(ret != null, "Message has already been taken");
74         message = null;
75         return ret;
76     }
77
78     @Override
79     public final GenericFutureListener<Future<Void>> takeListener() {
80         return this;
81     }
82
83     protected abstract void operationSuccessful();
84
85     protected final void failedRpc(final Throwable cause) {
86         final RpcError rpcError = buildRpcError(failureInfo, "check switch connection", cause);
87         result.set(RpcResultBuilder.<T>failed().withRpcError(rpcError).build());
88     }
89
90     protected final void successfulRpc(final T value) {
91         result.set(RpcResultBuilder.success(value).build());
92     }
93 }