Further fixes for APPC-1270
[appc.git] / appc-config / appc-config-adaptor / provider / src / main / java / org / onap / appc / ccadaptor / SshJcraftWrapper.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP : APPC
4  * ================================================================================
5  * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Copyright (C) 2017 Amdocs
8  * ================================================================================
9  * Modifications Copyright (C) 2018 Ericsson
10  * =============================================================================
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  *
15  *      http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  *
23  * ============LICENSE_END=========================================================
24  */
25
26 package org.onap.appc.ccadaptor;
27
28 import com.jcraft.jsch.Channel;
29 import com.jcraft.jsch.ChannelSftp;
30 import com.jcraft.jsch.ChannelShell;
31 import com.jcraft.jsch.ChannelSubsystem;
32 import com.jcraft.jsch.JSch;
33 import com.jcraft.jsch.JSchException;
34 import com.jcraft.jsch.Session;
35 import com.jcraft.jsch.SftpException;
36 import com.jcraft.jsch.UIKeyboardInteractive;
37 import com.jcraft.jsch.UserInfo;
38 import java.io.BufferedInputStream;
39 import java.io.BufferedReader;
40 import java.io.BufferedWriter;
41 import java.io.ByteArrayInputStream;
42 import java.io.ByteArrayOutputStream;
43 import java.io.DataInputStream;
44 import java.io.DataOutputStream;
45 import java.io.File;
46 import java.io.FileWriter;
47 import java.io.IOException;
48 import java.io.InputStream;
49 import java.io.InputStreamReader;
50 import java.io.OutputStream;
51 import java.io.RandomAccessFile;
52 import java.text.DateFormat;
53 import java.text.SimpleDateFormat;
54 import java.util.Calendar;
55 import java.util.Date;
56 import java.util.StringTokenizer;
57 import org.apache.commons.lang.StringUtils;
58
59 public class SshJcraftWrapper {
60
61     InputStream inputStream = null;
62     OutputStream outputStream = null;
63     DebugLog debugLog = new DebugLog();
64     private String debugLogFileName = "/tmp/sshJcraftWrapperDebug";
65     private TelnetListener listener = null;
66     private String routerLogFileName = null;
67     private String host = null;
68     private String RouterName = null;
69     private int BUFFER_SIZE = 512000;
70     char[] charBuffer = new char[BUFFER_SIZE];
71     private DataInputStream dis = null;
72     private BufferedReader reader = null;
73     private BufferedWriter out = null;
74     private File _tmpFile = null;
75     private JSch jsch = null;
76     private Session session = null;
77     private Channel channel = null;
78     private String tId = "";
79     private String aggregatedReceivedString = "";
80     private File extraDebugFile = new File("/tmp/sshJcraftWrapperDEBUG");
81     private String routerCmdType = "XML";
82     private String routerFileName = null;
83     private File jcraftReadSwConfigFileFromDisk = new File("/tmp/jcraftReadSwConfigFileFromDisk");
84     private String equipNameCode = null;
85     private String hostName = null;
86     private String userName = null;
87     private String passWord = null;
88     private StringBuffer charactersFromBufferFlush = new StringBuffer();
89     private Runtime runtime = Runtime.getRuntime();
90     private DebugLog dbLog = new DebugLog();
91
92     public SshJcraftWrapper() {
93         String fn = "SshJcraftWrapper.SshJcraftWrapper";
94         DebugLog.printRTAriDebug(fn, "SshJcraftWrapper has been instantated");
95         routerLogFileName = "/tmp/" + host;
96     }
97
98     public void connect(String hostname, String username, String password, String prompt, int timeOut)
99         throws IOException {
100         String fn = "SshJcraftWrapper.connect";
101         jsch = getJSch();
102         DebugLog.printRTAriDebug(fn,
103             "Attempting to connect to " + hostname + " username=" + username + " prompt='"
104                 + prompt + "' timeOut=" + timeOut);
105         DebugLog.printRTAriDebug(fn, "Trace A");
106         RouterName = hostname;
107         hostName = hostname;
108         userName = username;
109         passWord = password;
110         try {
111             session = jsch.getSession(username, hostname, 22);
112             UserInfo ui = new MyUserInfo();
113             session.setPassword(password);
114             session.setUserInfo(ui);
115             session.connect(timeOut);
116             channel = session.openChannel("shell");
117             session.setServerAliveCountMax(
118                 0); // If this is not set to '0', then socket timeout on all reads will not work!!!!
119             ((ChannelShell) channel).setPtyType("vt102");
120             inputStream = channel.getInputStream();
121             dis = new DataInputStream(inputStream);
122             reader = new BufferedReader(new InputStreamReader(dis), BUFFER_SIZE);
123             channel.connect();
124             DebugLog.printRTAriDebug(fn, "Successfully connected.");
125             DebugLog.printRTAriDebug(fn, "Flushing input buffer");
126             try {
127                 receiveUntil(prompt, 3000, "No cmd was sent, just waiting");
128             } catch (Exception e) {
129                 DebugLog.printRTAriDebug(fn, "Caught an Exception: Nothing to flush out.");
130             }
131         } catch (Exception e) {
132             DebugLog.printRTAriDebug(fn, "Caught an Exception. e=" + e);
133             throw new IOException(e.toString());
134         }
135     }
136
137     // User specifies the port number.
138     public void connect(String hostname, String username, String password, String prompt, int timeOut, int portNum)
139         throws IOException {
140         String fn = "SshJcraftWrapper.connect";
141         DebugLog.printRTAriDebug(fn,
142             ":Attempting to connect to " + hostname + " username=" + username + " prompt='"
143                 + prompt + "' timeOut=" + timeOut + " portNum=" + portNum);
144         RouterName = hostname;
145         hostName = hostname;
146         userName = username;
147         passWord = password;
148         RouterName = hostname;
149         jsch = getJSch();
150         try {
151             session = jsch.getSession(username, hostname, portNum);
152             UserInfo ui = new MyUserInfo();
153             session.setPassword(password);
154             session.setUserInfo(ui);
155             session.setConfig("StrictHostKeyChecking", "no");
156             DebugLog.printRTAriDebug(fn, ":StrictHostKeyChecking set to 'no'");
157
158             session.connect(timeOut);
159             session.setServerAliveCountMax(
160                 0); // If this is not set to '0', then socket timeout on all reads will not work!!!!
161             channel = session.openChannel("shell");
162             ((ChannelShell) channel).setPtyType("vt102");
163             inputStream = channel.getInputStream();
164             dis = new DataInputStream(inputStream);
165             reader = new BufferedReader(new InputStreamReader(dis), BUFFER_SIZE);
166             channel.connect();
167             DebugLog.printRTAriDebug(fn, ":Successfully connected.");
168             DebugLog.printRTAriDebug(fn, ":Flushing input buffer");
169             try {
170                 if (prompt.equals("]]>]]>")) {
171                     receiveUntil("]]>]]>", 10000, "No cmd was sent, just waiting");
172                 } else {
173                     receiveUntil(":~#", 5000, "No cmd was sent, just waiting");
174                 }
175             } catch (Exception e) {
176                 DebugLog.printRTAriDebug(fn, "Caught an Exception::: Nothing to flush out.");
177             }
178         } catch (Exception e) {
179             DebugLog.printRTAriDebug(fn, ":Caught an Exception. e=" + e);
180             dbLog.outputStackTrace(e);
181
182             throw new IOException(e.toString());
183         }
184     }
185
186
187     public String receiveUntil(String delimeters, int timeout, String cmdThatWasSent)
188         throws TimedOutException, IOException {
189         String fn = "SshJcraftWrapper.receiveUntil";
190         boolean match = false;
191         boolean cliPromptCmd = false;
192         StringBuffer sb2 = new StringBuffer();
193         StringBuffer sbReceive = new StringBuffer();
194         DebugLog.printRTAriDebug(fn,
195             "delimeters='" + delimeters + "' timeout=" + timeout + " cmdThatWasSent='" + cmdThatWasSent + "'");
196         appendToFile(debugLogFileName,
197             fn + " delimeters='" + delimeters + "' timeout=" + timeout + " cmdThatWasSent='" + cmdThatWasSent + "'\n");
198         String CmdThatWasSent = removeWhiteSpaceAndNewLineCharactersAroundString(cmdThatWasSent);
199         int readCounts = 0;
200         aggregatedReceivedString = "";
201         FileWriter fileWriter = null;
202
203         long deadline = new Date().getTime() + timeout;
204         try {
205             session.setTimeout(timeout);  // This is the socket timeout value.
206             while (!match) {
207                 if (new Date().getTime() > deadline) {
208                     DebugLog.printRTAriDebug(fn,
209                         "Throwing a TimedOutException: time in routine has exceed our deadline: RouterName:"
210                             + RouterName + " CmdThatWasSent=" + CmdThatWasSent);
211                     throw new TimedOutException("Timeout: time in routine has exceed our deadline");
212                 }
213                 try {
214                     delay(500);
215                 } catch (java.lang.InterruptedException ee) {
216                     Thread.currentThread().interrupt();
217                 }
218                 int len = reader.read(charBuffer, 0, BUFFER_SIZE);
219                 appendToFile(debugLogFileName, fn + " After reader.read cmd: len=" + len + "\n");
220                 if (len <= 0) {
221                     DebugLog.printRTAriDebug(fn,
222                         "Reader read " + len + " bytes. Looks like we timed out, router=" + RouterName);
223                     throw new TimedOutException("Received a SocketTimeoutException router=" + RouterName);
224                 }
225                 if (!cliPromptCmd) {
226                     if (cmdThatWasSent.indexOf("IOS_XR_uploadedSwConfigCmd") != -1) {
227                         if (out == null) {
228                             // This is a IOS XR sw config file. We will write it to the disk.
229                             timeout = timeout * 2;
230                             deadline = new Date().getTime() + timeout;
231                             DebugLog.printRTAriDebug(fn, "IOS XR upload for software config: timeout=" + timeout);
232                             StringTokenizer st = new StringTokenizer(cmdThatWasSent);
233                             st.nextToken();
234                             routerFileName = st.nextToken();
235                             fileWriter = new FileWriter(routerFileName);
236                             out = new BufferedWriter(fileWriter);
237                             routerLogFileName = "/tmp/" + RouterName;
238                             _tmpFile = new File(routerLogFileName);
239                             DebugLog.printRTAriDebug(fn,
240                                 "Will write the swConfigFile to disk, routerFileName=" + routerFileName);
241                         }
242                         out.write(charBuffer, 0, len);
243                         out.flush();
244                         appendToFile(debugLogFileName, fn + " Wrote " + len + " bytes to the disk\n");
245                         if (_tmpFile.exists()) {
246                             appendToRouterFile(routerLogFileName, len);
247                         }
248                         match = checkIfReceivedStringMatchesDelimeter(len, "\nXML>");
249                         if (match == true) {
250                             out.flush();
251                             out.close();
252                             out = null;
253                             return null;
254                         }
255                     } else {
256                         readCounts++;
257                         appendToFile(debugLogFileName,
258                             fn + " readCounts=" + readCounts + "  Reader read " + len + " of data\n");
259                         int c;
260                         sb2.setLength(0);
261                         for (int i = 0; i < len; i++) {
262                             c = charBuffer[i];
263                             if ((c != 7) && (c != 13) && (c != 0) && (c != 27)) {
264                                 sbReceive.append((char) charBuffer[i]);
265                                 sb2.append((char) charBuffer[i]);
266                             }
267                         }
268                         appendToRouterFile("/tmp/" + RouterName, len);
269                         if (listener != null) {
270                             listener.receivedString(sb2.toString());
271                         }
272
273                         appendToFile(debugLogFileName, fn + " Trace 1\n");
274                         match = checkIfReceivedStringMatchesDelimeter(delimeters, sb2.toString(), cmdThatWasSent);
275                         appendToFile(debugLogFileName, fn + " Trace 2\n");
276                         if (match == true) {
277                             appendToFile(debugLogFileName, fn + " Match was true, breaking...\n");
278                             break;
279                         }
280                     }
281                 }
282             }
283         } catch (JSchException e) {
284             DebugLog.printRTAriDebug(fn, "Caught an JSchException e=" + e.toString());
285             dbLog.outputStackTrace(e);
286             throw new TimedOutException(e.toString());
287         } catch (IOException ee) {
288             DebugLog.printRTAriDebug(fn, "Caught an IOException: ee=" + ee.toString());
289             dbLog.outputStackTrace(ee);
290             throw new TimedOutException(ee.toString());
291         } finally {
292             try {
293                 if (fileWriter != null) {
294                     fileWriter.close();
295                 }
296             } catch(IOException ex) {
297                 DebugLog.printRTAriDebug(fn, "Failed to close fileWriter output stream: ex=" + ex);
298             }
299         }
300         String result = stripOffCmdFromRouterResponse(sbReceive.toString());
301         DebugLog.printRTAriDebug(fn, "Leaving method successfully");
302         return result;
303     }
304
305     public boolean checkIfReceivedStringMatchesDelimeter(String delimeters, String receivedString,
306         String cmdThatWasSent) {
307         // The delimeters are in a '|' seperated string. Return true on the first match.
308         String fn = "SshJcraftWrapper.checkIfReceivedStringMatchesDelimeter";
309         appendToFile(debugLogFileName,
310             fn + " Entered:  delimeters='" + delimeters + " cmdThatWasSent='" + cmdThatWasSent + "' receivedString='"
311                 + receivedString + "'\n");
312         StringTokenizer st = new StringTokenizer(delimeters, "|");
313
314         if ((delimeters.indexOf("#$") != -1) || (routerCmdType.equals("CLI")))  // This would be an IOS XR, CLI command.
315         {
316             int x = receivedString.lastIndexOf("#");
317             int y = receivedString.length() - 1;
318             appendToFile(debugLogFileName, fn + " IOS XR, CLI command\n");
319             if (extraDebugFile.exists()) {
320                 appendToFile(debugLogFileName,
321                     fn + " :::cmdThatWasSent='" + cmdThatWasSent + "'  x=" + x + " y=" + y + "\n");
322             }
323             return (x != -1) && (y == x);
324         }
325         if (cmdThatWasSent.indexOf("show config") != -1) {
326             appendToFile(debugLogFileName, fn + "In the block for 'show config'\n");
327             while (st.hasMoreTokens()) {
328                 String delimeter = st.nextToken();
329                 // Make sure we don't get faked out by a response of " #".
330                 // Proc #0
331                 //   # signaling-local-address ipv6 FD00:F4D5:EA06:1::110:136:254
332                 // LAAR2#
333                 int x = receivedString.lastIndexOf(delimeter);
334                 if ((receivedString.lastIndexOf(delimeter) != -1) && (receivedString.lastIndexOf(" #") != x - 1)) {
335                     appendToFile(debugLogFileName, fn + "receivedString=\n'" + receivedString + "'\n");
336                     appendToFile(debugLogFileName,
337                         fn + "Returning true for the 'show config' command. We found our real delmeter. \n\n");
338                     return (true);
339                 }
340             }
341         } else {
342             aggregatedReceivedString = aggregatedReceivedString + receivedString;
343             _appendToFile("/tmp/aggregatedReceivedString.debug", aggregatedReceivedString);
344
345             while (st.hasMoreTokens()) {
346                 String delimeter = st.nextToken();
347                 appendToFile(debugLogFileName, fn + " Looking for an delimeter of:'" + delimeter + "'\n");
348                 appendToFile(debugLogFileName, fn + " receivedString='" + receivedString);
349                 if (aggregatedReceivedString.indexOf(delimeter) != -1) {
350                     DebugLog.printRTAriDebug(fn, "Found our delimeter, which was: '" + delimeter + "'");
351                     aggregatedReceivedString = "";
352                     return (true);
353                 }
354             }
355         }
356         return (false);
357     }
358
359     public boolean checkIfReceivedStringMatchesDelimeter(int len, String delimeter) {
360         String fnName = "SshJcraftWrapper.checkIfReceivedStringMatchesDelimeter:::";
361         int x;
362         int c;
363         String str = StringUtils.EMPTY;
364
365         if (jcraftReadSwConfigFileFromDisk()) {
366             DebugLog.printAriDebug(fnName, "jcraftReadSwConfigFileFromDisk block");
367             File fileName = new File(routerFileName);
368             appendToFile(debugLogFileName,
369                 fnName + " jcraftReadSwConfigFileFromDisk::: Will read the tail end of the file from the disk");
370             try {
371                 str = getLastFewLinesOfFile(fileName, 3);
372             } catch (IOException e) {
373                 DebugLog.printAriDebug(fnName, "Caught an Exception, e=" + e);
374                 dbLog.outputStackTrace(e);
375                 e.printStackTrace();
376             }
377         } else {
378             // When looking at the end of the charBuffer, don't include any linefeeds or spaces. We only want to make the smallest string possible.
379             for (x = len - 1; x >= 0; x--) {
380                 c = charBuffer[x];
381                 if (extraDebugFile.exists()) {
382                     appendToFile(debugLogFileName, fnName + " x=" + x + " c=" + c + "\n");
383                 }
384                 if ((c != 10) && (c != 32)) // Not a line feed nor a space.
385                 {
386                     break;
387                 }
388             }
389             if ((x + 1 - 13) >= 0) {
390                 str = new String(charBuffer, (x + 1 - 13), 13);
391                 appendToFile(debugLogFileName, fnName + " str:'" + str + "'\n");
392             } else {
393                 File fileName = new File(routerFileName);
394                 appendToFile(debugLogFileName,
395                     fnName + " Will read the tail end of the file from the disk, x=" + x + " len=" + len + " str::'"
396                         + str + "' routerFileName='" + routerFileName + "'\n");
397                 DebugLog.printAriDebug(fnName,
398                     "Will read the tail end of the file from the disk, x=" + x + " len=" + len + " str::'" + str
399                         + "' routerFileName='" + routerFileName + "'");
400                 try {
401                     str = getLastFewLinesOfFile(fileName, 3);
402                 } catch (IOException e) {
403                     DebugLog.printAriDebug(fnName, "Caught an Exception, e=" + e);
404                     dbLog.outputStackTrace(e);
405                     e.printStackTrace();
406                 }
407             }
408         }
409
410         if (str.indexOf(delimeter) != -1) {
411             DebugLog.printAriDebug(fnName, "str in break is:'" + str + "'" + " delimeter='" + delimeter + "'");
412             appendToFile(debugLogFileName,
413                 fnName + " str in break is:'" + str + " delimeter='" + delimeter + "'" + "'\n");
414             return (true);
415         } else {
416             appendToFile(debugLogFileName, fnName + " Returning false");
417             return (false);
418         }
419
420     }
421
422     public void closeConnection() {
423         String fn = "SshJcraftWrapper.closeConnection";
424         DebugLog.printRTAriDebug(fn, "Executing the closeConnection....");
425         inputStream = null;
426         outputStream = null;
427         dis = null;
428         charBuffer = null;
429         session.disconnect();
430         session = null;
431     }
432
433     public void send(String cmd) throws IOException {
434         String fn = "SshJcraftWrapper.send";
435         OutputStream out = channel.getOutputStream();
436         DataOutputStream dos = getDataOutputStream(out);
437         if ((cmd.charAt(cmd.length() - 1) != '\n') && (cmd.charAt(cmd.length() - 1) != '\r')) {
438             cmd += "\n";
439         }
440         int length = cmd.length();
441         int i = -1;
442         int nchars = 300000;
443         int ncharsTotalSent = 0;
444         int ncharsSent = 0;
445
446         appendToFile(debugLogFileName, fn + ": Sending: '" + cmd);
447         DebugLog.printRTAriDebug(fn, "Length of cmd is:" + length); // 2,937,706
448         try {
449             if (length > 600000) {
450                 int timeout = 9000;
451                 for (i = 0; i < length; i += nchars) {
452                     String Cmd = cmd.substring(i, Math.min(length, i + nchars));
453                     ncharsSent = Cmd.length();
454                     ncharsTotalSent = ncharsTotalSent + Cmd.length();
455                     DebugLog.printRTAriDebug(fn, "i=" + i + " Sending Cmd: ncharsSent=" + ncharsSent);
456                     dos.writeBytes(Cmd);
457                     dos.flush();
458                     try {
459                         DebugLog.printRTAriDebug(fn, ":::i=" + i + " length=" + length);
460                         if (ncharsSent < length) {
461                             receiveUntilBufferFlush(ncharsSent, timeout, "buffer flush  i=" + i);
462                         } else {
463                             DebugLog.printRTAriDebug(fn, "i=" + i + " No Waiting this time....");
464                             dos.flush();
465                         }
466                     } catch (Exception e) {
467                         DebugLog.printRTAriDebug(fn, "Caught an Exception: Nothing to flush out.");
468                     }
469                 }
470             } else {
471                 DebugLog.printRTAriDebug(fn, "Before executing the dos.writeBytes");
472                 dos.writeBytes(cmd);
473             }
474             dos.flush();
475             DebugLog.printRTAriDebug(fn, "Leaving method");
476             appendToFile(debugLogFileName, fn + ": Leaving method\n");
477         } catch (IOException e) {
478             DebugLog.printRTAriDebug(fn, "Caught an IOException. e=" + e);
479             dbLog.outputStackTrace(e);
480             throw new IOException(e.toString());
481         }
482     }
483
484
485     public void sendChar(int v) throws IOException {
486         String fn = "SshJcraftWrapper.sendChar";
487         OutputStream out = channel.getOutputStream();
488         DataOutputStream dos = getDataOutputStream(out);
489         try {
490             DebugLog.printRTAriDebug(fn, "Sending: '" + v + "'");
491             dos.writeChar(v);
492             dos.flush();
493         } catch (IOException e) {
494             DebugLog.printRTAriDebug(fn, "Caught an IOException. e=" + e);
495             throw new IOException(e.toString());
496         }
497     }
498
499     public void send(byte[] b, int off, int len) throws IOException {
500         String fn = "SshJcraftWrapper.send:byte[]";
501         OutputStream out = channel.getOutputStream();
502         DataOutputStream dos = getDataOutputStream(out);
503         try {
504             dos.write(b, off, len);
505             dos.flush();
506         } catch (IOException e) {
507             DebugLog.printRTAriDebug(fn, "Caught an IOException. e=" + e);
508             throw new IOException(e.toString());
509         }
510     }
511
512     public static class MyUserInfo implements UserInfo, UIKeyboardInteractive {
513
514         public String getPassword() {
515             return null;
516         }
517
518         public boolean promptYesNo(String str) {
519             return false;
520         }
521
522         public String getPassphrase() {
523             return null;
524         }
525
526         public boolean promptPassphrase(String message) {
527             return false;
528         }
529
530         public boolean promptPassword(String message) {
531             return false;
532         }
533
534         public void showMessage(String message) {
535         }
536
537         public String[] promptKeyboardInteractive(String destination,
538             String name,
539             String instruction,
540             String[] prompt,
541             boolean[] echo) {
542             return null;
543         }
544     }
545
546     public void addListener(TelnetListener listener) {
547         this.listener = listener;
548     }
549
550     public void appendToFile(String fileName, String dataToWrite) {
551         String fn = "SshJcraftWrapper.appendToFile";
552
553         try {
554             // First check to see if a file 'fileName' exist, if it does
555             // write to it. If it does not exist, don't write to it.
556             File tmpFile = new File(fileName);
557             if (tmpFile.exists()) {
558                 try(BufferedWriter out = new BufferedWriter(new FileWriter(fileName, true))) {
559                     out.write(getTheDate() + ": " + tId + ": " + dataToWrite);
560                 }
561             }
562         } catch (IOException e) {
563             DebugLog.printRTAriDebug(fn, "Caught an IOException: e=" + e);
564         } catch (Exception e) {
565             DebugLog.printRTAriDebug(fn, "Caught an Exception: e=" + e);
566         }
567     }
568
569     public void _appendToFile(String fileName, String dataToWrite) {
570         String fn = "SshJcraftWrapper.appendToFile";
571
572         try {
573             // First check to see if a file 'fileName' exist, if it does
574             // write to it. If it does not exist, don't write to it.
575             File tmpFile = new File(fileName);
576             if (tmpFile.exists()) {
577                 try(BufferedWriter out = new BufferedWriter(new FileWriter(fileName, true))) {
578                     out.write(dataToWrite);
579                 }
580             }
581         } catch (IOException e) {
582             DebugLog.printRTAriDebug(fn, "Caught an IOException: e=" + e);
583         } catch (Exception e) {
584             DebugLog.printRTAriDebug(fn, "Caught an Exception: e=" + e);
585         }
586     }
587
588
589     public String getTheDate() {
590         Calendar cal = Calendar.getInstance();
591         java.util.Date today = cal.getTime();
592         DateFormat df3 = new SimpleDateFormat("MM/dd/yyyy H:mm:ss  ");
593         return (df3.format(today));
594     }
595
596
597     public void appendToRouterFile(String fileName, StringBuffer dataToWrite) {
598         String fnName = "SshJcraftWrapper.appendToRouterFile";
599         DebugLog.printRTAriDebug(fnName, "Entered.... ");
600         try {
601             // First check to see if a file 'fileName' exist, if it does
602             // write to it. If it does not exist, don't write to it.
603             File tmpFile = new File(fileName);
604             {
605                 if (tmpFile.exists()) {
606                     try(BufferedWriter out = new BufferedWriter(new FileWriter(fileName, true))) {
607                         out.write(dataToWrite.toString());
608                     }
609                 }
610             }
611         } catch (IOException e) {
612             System.err.println("writeToFile() exception: " + e);
613             e.printStackTrace();
614         }
615     }
616
617     public void appendToRouterFile(String fileName, int len) {
618         try {
619             // First check to see if a file 'fileName' exist, if it does
620             // write to it. If it does not exist, don't write to it.
621             File tmpFile = new File(fileName);
622             if (tmpFile.exists()) {
623                 try(BufferedWriter out = new BufferedWriter(new FileWriter(fileName, true))) {
624                     out.write(charBuffer, 0, len);
625                 }
626             }
627         } catch (IOException e) {
628             System.err.println("writeToFile() exception: " + e);
629             e.printStackTrace();
630         }
631     }
632
633     public String removeWhiteSpaceAndNewLineCharactersAroundString(String str) {
634         if (str != null) {
635             StringTokenizer strTok = new StringTokenizer(str, "\n");
636             StringBuffer sb = new StringBuffer();
637
638             while (strTok.hasMoreTokens()) {
639                 String line = strTok.nextToken();
640                 sb.append(line);
641             }
642             return (sb.toString().trim());
643         } else {
644             return (str);
645         }
646     }
647
648     public String stripOffCmdFromRouterResponse(String routerResponse) {
649         // The session of SSH will echo the command sent to the router, in the router's response.
650         // Since all our commands are terminated by a '\n', strip off the first line
651         // of the response from the router. This first line contains the original command.
652
653         StringTokenizer rr = new StringTokenizer(routerResponse, "\n");
654         StringBuffer sb = new StringBuffer();
655
656         int numTokens = rr.countTokens();
657         if (numTokens > 1) {
658             rr.nextToken(); //Skip the first line.
659             while (rr.hasMoreTokens()) {
660                 sb.append(rr.nextToken() + '\n');
661             }
662         }
663         return (sb.toString());
664     }
665
666     public void setRouterCommandType(String type) {
667         String fn = "SshJcraftWrapper.setRouterCommandType";
668         this.routerCmdType = type;
669         DebugLog.printRTAriDebug(fn, "Setting routerCmdType to a value of '" + type + "'");
670     }
671
672     public String getLastFewLinesOfFile(File file, int linesToRead) throws IOException {
673         String fn = "SshJcraftWrapper.getLastFewLinesOfFile";
674         String tail = "";
675         try(RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r")) {
676             int lines = 0;
677             StringBuilder builder = new StringBuilder();
678             long length = file.length();
679             length--;
680             randomAccessFile.seek(length);
681             for (long seek = length; seek >= 0; --seek) {
682                 randomAccessFile.seek(seek);
683                 char c = (char) randomAccessFile.read();
684                 builder.append(c);
685                 if (c == '\n') {
686                     builder = builder.reverse();
687                     tail = builder.toString() + tail;
688                     lines++;
689                     builder.setLength(0);
690                     if (lines == linesToRead) {
691                         break;
692                     }
693                 }
694             }
695         }
696         if (!jcraftReadSwConfigFileFromDisk()) {
697             DebugLog.printRTAriDebug(fn, "tail='" + tail + "'");
698         }
699         appendToFile(debugLogFileName, "tail='" + tail + "'\n");
700         return tail;
701     }
702
703     public boolean jcraftReadSwConfigFileFromDisk() {
704         if (jcraftReadSwConfigFileFromDisk.exists()) {
705             return (true);
706         } else {
707             return (false);
708         }
709     }
710
711     public String getEquipNameCode() {
712         return (equipNameCode);
713
714     }
715
716     public void setEquipNameCode(String equipNameCode) {
717         this.equipNameCode = equipNameCode;
718     }
719
720     public String getRouterName() {
721         return (RouterName);
722     }
723
724     // Routine does reads until it has read 'nchars' or times out.
725     public void receiveUntilBufferFlush(int ncharsSent, int timeout, String message)
726         throws TimedOutException, IOException {
727         String fn = "SshJcraftWrapper.receiveUntilBufferFlush";
728         DebugLog.printRTAriDebug(fn, "ncharsSent=" + ncharsSent + " timeout=" + timeout + " " + message);
729         int ncharsTotalReceived = 0;
730         int ncharsRead = 0;
731         charactersFromBufferFlush.setLength(0);
732
733         long deadline = new Date().getTime() + timeout;
734         logMemoryUsage();
735         try {
736             session.setTimeout(timeout);  // This is the socket timeout value.
737             while (true) {
738                 if (new Date().getTime() > deadline) {
739                     DebugLog.printRTAriDebug(fn,
740                         "Throwing a TimedOutException: time in routine has exceed our deadline: ncharsSent="
741                             + ncharsSent + " ncharsTotalReceived=" + ncharsTotalReceived);
742                     throw new TimedOutException("Timeout: time in routine has exceed our deadline");
743                 }
744                 ncharsRead = reader.read(charBuffer, 0, BUFFER_SIZE);
745                 if (listener != null) {
746                     listener.receivedString(String.copyValueOf(charBuffer, 0, ncharsRead));
747                 }
748                 appendToRouterFile("/tmp/" + RouterName, ncharsRead);
749                 ncharsTotalReceived = ncharsTotalReceived + ncharsRead;
750                 if (ncharsTotalReceived >= ncharsSent) {
751                     DebugLog.printRTAriDebug(fn,
752                         "Received the correct number of characters, ncharsSent=" + ncharsSent + " ncharsTotalReceived="
753                             + ncharsTotalReceived);
754                     logMemoryUsage();
755                     return;
756                 }
757             }
758         } catch (JSchException e) {
759             DebugLog.printRTAriDebug(fn, "Caught an JSchException e=" + e);
760             DebugLog.printRTAriDebug(fn,
761                 "ncharsSent=" + ncharsSent + " ncharsTotalReceived=" + ncharsTotalReceived + " ncharsRead="
762                     + ncharsRead);
763             throw new TimedOutException(e.toString());
764         }
765     }
766
767     public String getHostName() {
768         return (hostName);
769     }
770
771     public String getUserName() {
772         return (userName);
773     }
774
775     public String getPassWord() {
776         return (passWord);
777     }
778
779     public void sftpPut(String sourcePath, String destDirectory) throws IOException {
780         // delegate to duplicate method
781         put(sourcePath, destDirectory);
782     }
783
784
785     public void SftpPut(String stringOfData, String fullPathDest) throws IOException {
786         String fn = "SshJcraftWrapper.Sftp";
787         try {
788             Session sftpSession = jsch.getSession(userName, hostName, 22);
789             UserInfo ui = new MyUserInfo();
790             sftpSession.setPassword(passWord);
791             sftpSession.setUserInfo(ui);
792             sftpSession.connect(30 * 1000);
793             DebugLog.printRTAriDebug(fn, "Opening up an sftp channel....");
794             ChannelSftp sftp = (ChannelSftp) sftpSession.openChannel("sftp");
795             DebugLog.printRTAriDebug(fn, "Connecting....");
796             sftp.connect();
797             InputStream is = new ByteArrayInputStream(stringOfData.getBytes());
798             DebugLog.printRTAriDebug(fn, "Sending stringOfData --> " + fullPathDest);
799             sftp.put(is, fullPathDest, ChannelSftp.OVERWRITE);
800             DebugLog.printRTAriDebug(fn, "Sent successfully");
801             sftpSession.disconnect();
802         } catch (Exception e) {
803             DebugLog.printRTAriDebug(fn, "Caught an Exception, e=" + e);
804             throw new IOException(e.toString());
805         }
806     }
807
808     public String sftpGet(String fullFilePathName) throws IOException {
809         String fn = "SshJcraftWrapper.Sftp";
810         try {
811             Session sftpSession = jsch.getSession(userName, hostName, 22);
812             UserInfo ui = new MyUserInfo();
813             sftpSession.setPassword(passWord);
814             sftpSession.setUserInfo(ui);
815             sftpSession.connect(30 * 1000);
816             DebugLog.printRTAriDebug(fn, "Opening up an sftp channel....");
817             ChannelSftp sftp = (ChannelSftp) sftpSession.openChannel("sftp");
818             DebugLog.printRTAriDebug(fn, "Connecting....");
819             sftp.connect();
820             InputStream in = null;
821             in = sftp.get(fullFilePathName);
822             String sftpFileString = readInputStreamAsString(in);
823             DebugLog.printRTAriDebug(fn, "Retreived successfully");
824             sftpSession.disconnect();
825             return (sftpFileString);
826         } catch (Exception e) {
827             DebugLog.printRTAriDebug(fn, "Caught an Exception, e=" + e);
828             throw new IOException(e.toString());
829         }
830     }
831
832     public static String readInputStreamAsString(InputStream in) throws IOException {
833         BufferedInputStream bis = new BufferedInputStream(in);
834         ByteArrayOutputStream buf = new ByteArrayOutputStream();
835         int result = bis.read();
836         while (result != -1) {
837             byte b = (byte) result;
838             buf.write(b);
839             result = bis.read();
840         }
841         return buf.toString();
842     }
843
844
845     public void logMemoryUsage() {
846         String fn = "SshJcraftWrapper.logMemoryUsage";
847         int mb = 1024 * 1024;
848         long usedMemory;
849         long maxMemoryAdvailable;
850         long memoryLetfOnHeap;
851         maxMemoryAdvailable = (runtime.maxMemory() / mb);
852         usedMemory = ((runtime.totalMemory() / mb) - (runtime.freeMemory() / mb));
853         memoryLetfOnHeap = maxMemoryAdvailable - usedMemory;
854         DebugLog.printAriDebug(fn,
855             "maxMemoryAdvailable=" + maxMemoryAdvailable + " usedMemory=" + usedMemory + " memoryLetfOnHeap="
856                 + memoryLetfOnHeap);
857     }
858
859     // ----------------------------------------------------------------------------
860     // ----------------------------------------------------------------------------
861     // ----------------------------------------------------------------------------
862     // ----------------------------------------------------------------------------
863
864
865     // User specifies the port number, and the subsystem
866     public void connect(String hostname, String username, String password, String prompt, int timeOut, int portNum,
867         String subsystem) throws IOException {
868         String fn = "SshJcraftWrapper.connect";
869
870         DebugLog.printRTAriDebug(fn,
871             ":::Attempting to connect to " + hostname + " username=" + username + " prompt='"
872                 + prompt + "' timeOut=" + timeOut + " portNum=" + portNum + " subsystem=" + subsystem);
873         RouterName = hostname;
874         jsch = getJSch();
875         try {
876             session = jsch.getSession(username, hostname, portNum);
877             UserInfo ui = new MyUserInfo();
878             session.setPassword(password);
879             session.setUserInfo(ui);
880             session.setConfig("StrictHostKeyChecking", "no");
881             session.connect(timeOut);
882             session.setServerAliveCountMax(
883                 0); // If this is not set to '0', then socket timeout on all reads will not work!!!!
884             channel = session.openChannel("subsystem");
885             ((ChannelSubsystem) channel).setSubsystem(subsystem);
886             ((ChannelSubsystem) channel).setPty(true);
887
888             inputStream = channel.getInputStream();
889             dis = new DataInputStream(inputStream);
890             reader = new BufferedReader(new InputStreamReader(dis), BUFFER_SIZE);
891             channel.connect();
892             DebugLog.printRTAriDebug(fn, "Successfully connected.");
893             DebugLog.printRTAriDebug(fn, "Five second sleep....");
894             try {
895                 delay(5000);
896             } catch (java.lang.InterruptedException ee) {
897                 Thread.currentThread().interrupt();
898             }
899         } catch (Exception e) {
900             DebugLog.printRTAriDebug(fn, "Caught an Exception. e=" + e);
901             throw new IOException(e.toString());
902         }
903     }
904
905     public void connect(String hostName, String username, String password, int portNumber) throws IOException {
906         String fn = "SshJcraftWrapper.connect";
907         jsch = getJSch();
908         DebugLog.printRTAriDebug(fn,
909             "::Attempting to connect to " + hostName + " username=" + username + " portNumber=" + portNumber);
910         DebugLog.printRTAriDebug(fn, "Trace C");
911         RouterName = hostName;
912         this.hostName = hostName;
913         userName = username;
914         passWord = password;
915         try {
916             java.util.Properties config = new java.util.Properties();
917             config.put("StrictHostKeyChecking", "no");
918             session = jsch.getSession(username, hostName, 22);
919             UserInfo ui = new MyUserInfo();
920             session.setConfig(config);
921             session.setPassword(password);
922             session.setUserInfo(ui);
923             session.connect(30000);
924             channel = session.openChannel("shell");
925             session.setServerAliveCountMax(
926                 0); // If this is not set to '0', then socket timeout on all reads will not work!!!!
927             ((ChannelShell) channel).setPtyType("vt102");
928             inputStream = channel.getInputStream();
929             dis = new DataInputStream(inputStream);
930             reader = new BufferedReader(new InputStreamReader(dis), BUFFER_SIZE);
931             channel.connect();
932             DebugLog.printRTAriDebug(fn, "::Successfully connected.");
933             DebugLog.printRTAriDebug(fn, "::Flushing input buffer");
934             try {
935                 receiveUntil(":~#", 9000, "No cmd was sent, just waiting, but we can stop on a '~#'");
936             } catch (Exception e) {
937                 DebugLog.printRTAriDebug(fn, "Caught an Exception::: Nothing to flush out.");
938             }
939
940         } catch (Exception e) {
941             DebugLog.printRTAriDebug(fn, "Caught an Exception. e=" + e);
942             throw new IOException(e.toString());
943         }
944     }
945
946
947     public void put(String sourcePath, String destDirectory) throws IOException {
948         String fn = "SshJcraftWrapper.sftp";
949         try {
950             Session sftpSession = jsch.getSession(userName, hostName, 22);
951             UserInfo ui = new MyUserInfo();
952             sftpSession.setPassword(passWord);
953             sftpSession.setUserInfo(ui);
954             sftpSession.connect(30 * 1000);
955             DebugLog.printRTAriDebug(fn, "Opening up an sftp channel....");
956             ChannelSftp sftp = (ChannelSftp) sftpSession.openChannel("sftp");
957             DebugLog.printRTAriDebug(fn, "Connecting....");
958             sftp.connect();
959             DebugLog.printRTAriDebug(fn, "Sending " + sourcePath + " --> " + destDirectory);
960             sftp.put(sourcePath, destDirectory, ChannelSftp.OVERWRITE);
961             DebugLog.printRTAriDebug(fn, "Sent successfully");
962             sftpSession.disconnect();
963         } catch (Exception e) {
964             DebugLog.printRTAriDebug(fn, "Caught an Exception, e=" + e);
965             throw new IOException(e.toString());
966         }
967     }
968
969     public void put(InputStream is, String fullPathDest, String hostName, String userName, String passWord)
970         throws IOException {
971         String fn = "SshJcraftWrapper.put";
972         Session sftpSession = null;
973         try {
974             DebugLog.printRTAriDebug(fn, "userName=" + userName + " hostName=" + hostName);
975             jsch = getJSch();
976             java.util.Properties config = new java.util.Properties();
977             config.put("StrictHostKeyChecking", "no");
978             sftpSession = jsch.getSession(userName, hostName, 22);
979             UserInfo ui = new MyUserInfo();
980             sftpSession.setPassword(passWord);
981             sftpSession.setUserInfo(ui);
982             sftpSession.setConfig(config);
983             sftpSession.connect(30 * 1000);
984             DebugLog.printRTAriDebug(fn, "Opening up an sftp channel....");
985             ChannelSftp sftp = (ChannelSftp) sftpSession.openChannel("sftp");
986             DebugLog.printRTAriDebug(fn, "Connecting....");
987             sftp.connect();
988             String oldFiles = fullPathDest + "*";
989             DebugLog.printRTAriDebug(fn, "Deleting old files --> " + oldFiles);
990             try {
991                 sftp.rm(oldFiles);
992                 DebugLog.printRTAriDebug(fn, "Sending stringOfData --> " + fullPathDest);
993             } catch (SftpException sft) {
994                 String exp = "No such file";
995                 if (sft.getMessage() != null && sft.getMessage().contains(exp)) {
996                     DebugLog.printRTAriDebug(fn, "No files found -- Continue");
997                 } else {
998                     DebugLog.printRTAriDebug(fn, "Exception while sftp.rm " + sft.getMessage());
999                     throw sft;
1000                 }
1001             }
1002             sftp.put(is, fullPathDest, ChannelSftp.OVERWRITE);
1003             DebugLog.printRTAriDebug(fn, "Sent successfully");
1004         } catch (Exception e) {
1005             DebugLog.printRTAriDebug(fn, "Caught an Exception, e=" + e);
1006             throw new IOException(e.toString());
1007         } finally {
1008             if(sftpSession != null) {
1009                 sftpSession.disconnect();
1010             }
1011         }
1012     }
1013
1014
1015     public String get(String fullFilePathName, String hostName, String userName, String passWord) throws IOException {
1016         String fn = "SshJcraftWrapper.get";
1017         Session sftpSession = null;
1018         try {
1019             DebugLog.printRTAriDebug(fn, "userName=" + userName + " hostName=" + hostName);
1020             jsch = getJSch();
1021             sftpSession = jsch.getSession(userName, hostName, 22);
1022             java.util.Properties config = new java.util.Properties();
1023             config.put("StrictHostKeyChecking", "no");
1024             UserInfo ui = new MyUserInfo();
1025             sftpSession.setPassword(passWord);
1026             sftpSession.setUserInfo(ui);
1027             sftpSession.setConfig(config);
1028             sftpSession.connect(30 * 1000);
1029             DebugLog.printRTAriDebug(fn, "Opening up an sftp channel....");
1030             ChannelSftp sftp = (ChannelSftp) sftpSession.openChannel("sftp");
1031             DebugLog.printRTAriDebug(fn, "Connecting....");
1032             sftp.connect();
1033             InputStream in = sftp.get(fullFilePathName);
1034             String sftpFileString = readInputStreamAsString(in);
1035             DebugLog.printRTAriDebug(fn, "Retreived successfully");
1036             return sftpFileString;
1037         } catch (Exception e) {
1038             DebugLog.printRTAriDebug(fn, "Caught an Exception, e=" + e);
1039             throw new IOException(e.toString());
1040         } finally {
1041             if(sftpSession != null) {
1042                 sftpSession.disconnect();
1043             }
1044         }
1045     }
1046
1047     public String send(String cmd, String delimiter) throws IOException {
1048         String fn = "SshJcraftWrapper.send";
1049         OutputStream out = channel.getOutputStream();
1050         DataOutputStream dos = getDataOutputStream(out);
1051
1052         if ((cmd.charAt(cmd.length() - 1) != '\n') && (cmd.charAt(cmd.length() - 1) != '\r')) {
1053             cmd += "\n";
1054         }
1055         int length = cmd.length();
1056         int i = -1;
1057         int nchars = 300000;
1058         int ncharsTotalSent = 0;
1059         int ncharsSent = 0;
1060
1061         DebugLog.printRTAriDebug(fn, "Length of cmd is:" + length); // 2,937,706
1062         try {
1063             if (length > 600000) {
1064                 int timeout = 9000;
1065                 for (i = 0; i < length; i += nchars) {
1066                     String Cmd = cmd.substring(i, Math.min(length, i + nchars));
1067                     ncharsSent = Cmd.length();
1068                     ncharsTotalSent = ncharsTotalSent + Cmd.length();
1069                     DebugLog.printRTAriDebug(fn, "i=" + i + " Sending Cmd: ncharsSent=" + ncharsSent);
1070                     dos.writeBytes(Cmd);
1071                     dos.flush();
1072                     try {
1073                         DebugLog.printRTAriDebug(fn, ":::i=" + i + " length=" + length);
1074                         if (ncharsSent < length) {
1075                             receiveUntilBufferFlush(ncharsSent, timeout, "buffer flush  i=" + i);
1076                         } else {
1077                             DebugLog.printRTAriDebug(fn, "i=" + i + " No Waiting this time....");
1078                             dos.flush();
1079                         }
1080                     } catch (Exception e) {
1081                         DebugLog.printRTAriDebug(fn, "Caught an Exception: Nothing to flush out.");
1082                     }
1083                 }
1084             } else {
1085                 DebugLog.printRTAriDebug(fn, "Before executing the dos.writeBytes");
1086                 dos.writeBytes(cmd);
1087             }
1088             dos.flush();
1089             // Now lets get the response.
1090             String response = receiveUntil(delimiter, 300000, cmd);
1091             DebugLog.printRTAriDebug(fn, "Leaving method");
1092             return (response);
1093         } catch (IOException e) {
1094             DebugLog.printRTAriDebug(fn, "Caught an IOException. e=" + e);
1095             throw new IOException(e.toString());
1096         }
1097     }
1098
1099     protected JSch getJSch() {
1100         return new JSch();
1101     }
1102
1103     protected DataOutputStream getDataOutputStream(OutputStream out) {
1104         return new DataOutputStream(out);
1105     }
1106
1107     protected void delay(int milliseconds) throws InterruptedException {
1108         Thread.sleep(5000);
1109     }
1110 }