1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.waarp.commandexec.client;
21
22 import io.netty.channel.Channel;
23 import io.netty.channel.ChannelHandlerContext;
24 import io.netty.channel.SimpleChannelInboundHandler;
25 import org.waarp.commandexec.utils.LocalExecDefaultResult;
26 import org.waarp.commandexec.utils.LocalExecResult;
27 import org.waarp.common.crypto.ssl.WaarpSslUtility;
28 import org.waarp.common.future.WaarpFuture;
29 import org.waarp.common.logging.WaarpLogger;
30 import org.waarp.common.logging.WaarpLoggerFactory;
31 import org.waarp.common.utility.WaarpNettyUtil;
32
33
34
35
36 public class LocalExecClientHandler
37 extends SimpleChannelInboundHandler<String> {
38
39
40
41
42 private static final WaarpLogger logger =
43 WaarpLoggerFactory.getLogger(LocalExecClientHandler.class);
44
45 protected LocalExecResult result;
46 protected StringBuilder back;
47 protected boolean firstMessage = true;
48 protected WaarpFuture future;
49 protected final LocalExecClientInitializer factory;
50 protected long delay;
51 protected String command;
52 protected Channel channel;
53 protected final WaarpFuture ready = new WaarpFuture(true);
54
55
56
57
58 public LocalExecClientHandler(final LocalExecClientInitializer factory) {
59 this.factory = factory;
60 }
61
62
63
64
65
66
67
68 public final void initExecClient(final long delay, final String command) {
69 result = new LocalExecResult(LocalExecDefaultResult.NoStatus);
70 back = new StringBuilder();
71 firstMessage = true;
72 future = new WaarpFuture(true);
73 this.delay = delay;
74 this.command = command;
75
76 if (!ready.awaitOrInterruptible() && channel == null) {
77 throw new RuntimeException("Cannot get client connected");
78 }
79 logger.debug("write command: {}", this.command);
80 if (this.delay != 0) {
81 WaarpNettyUtil.awaitOrInterrupted(
82 channel.writeAndFlush(this.delay + " " + this.command + '\n'));
83 } else {
84 WaarpNettyUtil.awaitOrInterrupted(
85 channel.writeAndFlush(this.command + '\n'));
86 }
87 }
88
89 @Override
90 public void channelActive(final ChannelHandlerContext ctx) throws Exception {
91 channel = ctx.channel();
92 factory.addChannel(channel);
93 ready.setSuccess();
94 super.channelActive(ctx);
95 }
96
97
98
99
100
101
102
103
104 @Override
105 public void channelInactive(final ChannelHandlerContext ctx)
106 throws Exception {
107 if (future == null || !future.isDone()) {
108
109 finalizeMessage();
110 }
111 super.channelInactive(ctx);
112 }
113
114
115
116
117 private void finalizeMessage() {
118 if (result == null) {
119 if (future != null) {
120 future.cancel();
121 }
122 return;
123 }
124 if (firstMessage) {
125 result.set(LocalExecDefaultResult.NoMessage);
126 } else {
127 result.setResult(back.toString());
128 }
129 if (result.getStatus() < 0) {
130 if (result.getException() != null) {
131 future.setFailure(result.getException());
132 } else {
133 future.cancel();
134 }
135 } else {
136 future.setSuccess();
137 }
138 }
139
140
141
142
143
144
145 public final LocalExecResult waitFor(final long delay) {
146 if (delay <= 0) {
147 future.awaitOrInterruptible();
148 } else {
149 future.awaitOrInterruptible(delay);
150 }
151 result.setSuccess(future.isSuccess());
152 return result;
153 }
154
155
156
157
158 public final void actionBeforeClose(final Channel channel) {
159
160 }
161
162 @Override
163 protected void channelRead0(final ChannelHandlerContext ctx, String mesg) {
164
165
166 if (firstMessage) {
167 firstMessage = false;
168 final int pos = mesg.indexOf(' ');
169 try {
170 result.setStatus(Integer.parseInt(mesg.substring(0, pos)));
171 } catch (final NumberFormatException e1) {
172
173 logger.debug(
174 command + ':' + "Bad Transmission: " + mesg + "\n\t" + back);
175 result.set(LocalExecDefaultResult.BadTransmition);
176 back.append(mesg);
177 actionBeforeClose(ctx.channel());
178 WaarpSslUtility.closingSslChannel(ctx.channel());
179 return;
180 }
181 mesg = mesg.substring(pos + 1);
182 if (mesg.startsWith(LocalExecDefaultResult.ENDOFCOMMAND)) {
183 logger.debug("{}:Receive End of Command", command);
184 result.setResult(LocalExecDefaultResult.NoMessage.getResult());
185 back.append(result.getResult());
186 finalizeMessage();
187 } else {
188 result.setResult(mesg);
189 back.append(mesg);
190 }
191 } else if (mesg.startsWith(LocalExecDefaultResult.ENDOFCOMMAND)) {
192 logger.debug("{}:Receive End of Command", command);
193 finalizeMessage();
194 } else {
195 back.append('\n').append(mesg);
196 }
197 }
198
199 @Override
200 public void exceptionCaught(final ChannelHandlerContext ctx,
201 final Throwable cause) {
202 logger.warn(command + ':' +
203 "Unexpected exception from Outband while get information: " +
204 firstMessage, cause);
205 if (firstMessage) {
206 firstMessage = false;
207 result.set(LocalExecDefaultResult.BadTransmition);
208 result.setException((Exception) cause);
209 back = new StringBuilder("Error in LocalExec: ").append(
210 result.getException().getMessage()).append('\n');
211 } else {
212 back.append("\nERROR while receiving answer: ");
213 result.setException((Exception) cause);
214 back.append(result.getException().getMessage()).append('\n');
215 }
216 actionBeforeClose(ctx.channel());
217 WaarpSslUtility.closingSslChannel(ctx.channel());
218 }
219 }