2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Copyright (C) 2017 Amdocs
8 * =============================================================================
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
21 * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22 * ============LICENSE_END=========================================================
25 package org.onap.appc.ccadaptor;
27 import com.att.eelf.configuration.EELFLogger;
28 import com.att.eelf.configuration.EELFManager;
29 import com.jcraft.jsch.Channel;
30 import com.jcraft.jsch.ChannelSftp;
31 import com.jcraft.jsch.ChannelShell;
32 import com.jcraft.jsch.ChannelSubsystem;
33 import com.jcraft.jsch.JSch;
34 import com.jcraft.jsch.JSchException;
35 import com.jcraft.jsch.Session;
36 import com.jcraft.jsch.SftpException;
37 import com.jcraft.jsch.UIKeyboardInteractive;
38 import com.jcraft.jsch.UserInfo;
39 import java.io.BufferedInputStream;
40 import java.io.BufferedReader;
41 import java.io.BufferedWriter;
42 import java.io.ByteArrayInputStream;
43 import java.io.ByteArrayOutputStream;
44 import java.io.DataInputStream;
45 import java.io.DataOutputStream;
47 import java.io.FileWriter;
48 import java.io.IOException;
49 import java.io.InputStream;
50 import java.io.InputStreamReader;
51 import java.io.OutputStream;
52 import java.io.RandomAccessFile;
53 import java.text.DateFormat;
54 import java.text.SimpleDateFormat;
55 import java.util.Calendar;
56 import java.util.Date;
57 import java.util.StringTokenizer;
58 import java.util.concurrent.TimeUnit;
59 import javax.annotation.Nonnull;
60 import org.apache.commons.lang.StringUtils;
62 public class SshJcraftWrapper {
64 private static final EELFLogger log = EELFManager.getInstance().getLogger(SshJcraftWrapper.class);
66 private static final int BUFFER_SIZE = 512000;
67 private InputStream inputStream = null;
68 private TelnetListener listener = null;
69 private String routerLogFileName = null;
70 private String routerName = null;
71 private char[] charBuffer = new char[BUFFER_SIZE];
72 private DataInputStream dis = null;
73 private BufferedReader reader = null;
74 private BufferedWriter out = null;
75 private File tmpFile = null;
76 private JSch jsch = null;
77 private Session session = null;
78 private Channel channel = null;
79 private String aggregatedReceivedString = "";
80 private String routerCmdType = "XML";
81 private String routerFileName = null;
82 private File jcraftReadSwConfigFileFromDisk = new File("/tmp/jcraftReadSwConfigFileFromDisk");
83 private String equipNameCode = null;
84 private String hostName = null;
85 private String userName = null;
86 private String passWord = null;
87 private Runtime runtime = Runtime.getRuntime();
89 public void connect(String hostname, String username, String password, String prompt, int timeOut)
92 log.debug("Attempting to connect to {0} username={1} prompt='{2}' timeOut={3}",
93 hostname, username, prompt, timeOut);
94 routerName = hostname;
99 session = jsch.getSession(username, hostname, 22);
100 UserInfo ui = new MyUserInfo();
101 session.setPassword(password);
102 session.setUserInfo(ui);
103 session.connect(timeOut);
104 channel = session.openChannel("shell");
105 session.setServerAliveCountMax(
106 0); // If this is not set to '0', then socket timeout on all reads will not work!!!!
107 ((ChannelShell) channel).setPtyType("vt102");
108 inputStream = channel.getInputStream();
109 dis = new DataInputStream(inputStream);
110 reader = new BufferedReader(new InputStreamReader(dis), BUFFER_SIZE);
112 log.info("Successfully connected. Flushing input buffer.");
114 receiveUntil(prompt, 3000, "No cmd was sent, just waiting");
115 } catch (Exception e) {
116 log.warn("Caught an Exception: Nothing to flush out.", e);
118 } catch (Exception e) {
119 log.error("Could not connect to host=" + hostname, e);
120 throw new IOException(e.toString());
124 // User specifies the port number.
125 public void connect(String hostname, String username, String password, String prompt, int timeOut, int portNum)
127 log.debug("Attempting to connect to {0} username={1} prompt='{2}' timeOut={3} portNum={4}",
128 hostname, username, prompt, timeOut, portNum);
129 routerName = hostname;
135 session = jsch.getSession(username, hostname, portNum);
136 UserInfo ui = new MyUserInfo();
137 session.setPassword(password);
138 session.setUserInfo(ui);
139 session.setConfig("StrictHostKeyChecking", "no");
140 log.debug("StrictHostKeyChecking set to 'no'");
142 session.connect(timeOut);
143 session.setServerAliveCountMax(
144 0); // If this is not set to '0', then socket timeout on all reads will not work!!!!
145 channel = session.openChannel("shell");
146 ((ChannelShell) channel).setPtyType("vt102");
147 inputStream = channel.getInputStream();
148 dis = new DataInputStream(inputStream);
149 reader = new BufferedReader(new InputStreamReader(dis), BUFFER_SIZE);
151 log.info("Successfully connected. Flushing input buffer.");
153 if ("]]>]]>".equals(prompt)) {
154 receiveUntil("]]>]]>", 10000, "No cmd was sent, just waiting");
156 receiveUntil(":~#", 5000, "No cmd was sent, just waiting");
158 } catch (Exception e) {
159 log.warn("Caught an Exception: Nothing to flush out.", e);
161 } catch (Exception e) {
162 log.error("Could not connect to host=" + hostname, e);
163 throw new IOException(e.toString());
168 public String receiveUntil(String delimeters, int timeout, String cmdThatWasSent) throws IOException {
169 boolean match = false;
170 boolean cliPromptCmd = false;
171 StringBuilder sb = new StringBuilder();
172 StringBuilder sbReceive = new StringBuilder();
173 log.debug("delimeters='{0}' timeout={1} cmdThatWasSent='{2}'", delimeters, timeout, cmdThatWasSent);
175 aggregatedReceivedString = "";
176 FileWriter fileWriter = null;
178 long deadline = new Date().getTime() + timeout;
180 session.setTimeout(timeout); // This is the socket timeout value.
182 if (new Date().getTime() > deadline) {
183 String formattedCmd = removeWhiteSpaceAndNewLineCharactersAroundString(cmdThatWasSent);
184 log.error("Routine has timed out: routerName={0} CmdThatWasSent={1}", routerName, formattedCmd);
185 throw new TimedOutException("Routine has timed out");
189 } catch (java.lang.InterruptedException ee) {
190 Thread.currentThread().interrupt();
192 int len = reader.read(charBuffer, 0, BUFFER_SIZE);
193 log.trace("After reader. Read command len={0}", len);
195 log.error("Reader failed to read any bytes. Suspected socket timeout, router={0}", routerName);
196 throw new TimedOutException("Received a SocketTimeoutException router=" + routerName);
199 if (cmdThatWasSent.indexOf("IOS_XR_uploadedSwConfigCmd") != -1) {
201 // This is a IOS XR sw config file. We will write it to the disk.
202 timeout = timeout * 2;
203 deadline = new Date().getTime() + timeout;
204 log.debug("IOS XR upload for software config: timeout={0}", timeout);
205 StringTokenizer st = new StringTokenizer(cmdThatWasSent);
207 routerFileName = st.nextToken();
208 fileWriter = new FileWriter(routerFileName);
209 out = new BufferedWriter(fileWriter);
210 routerLogFileName = "/tmp/" + routerName;
211 tmpFile = new File(routerLogFileName);
212 log.debug("Prepared for writing swConfigFile to disk, routerFileName=" + routerFileName);
214 out.write(charBuffer, 0, len);
216 log.debug("{0} bytes has been written to the disk", len);
217 if (tmpFile.exists()) {
218 appendToRouterFile(routerLogFileName, len);
220 match = checkIfReceivedStringMatchesDelimeter(len, "\nXML>");
229 log.debug("Reader read {0} of data within {1} read iteration", len, readCounts);
232 for (int i = 0; i < len; i++) {
234 if ((c != 7) && (c != 13) && (c != 0) && (c != 27)) {
235 sbReceive.append(charBuffer[i]);
236 sb.append(charBuffer[i]);
239 appendToRouterFile("/tmp/" + routerName, len);
240 if (listener != null) {
241 listener.receivedString(sb.toString());
243 match = checkIfReceivedStringMatchesDelimeter(delimeters, sb.toString(), cmdThatWasSent);
245 log.trace("Match was true, breaking the loop.");
250 log.trace("cliPromptCmd");
252 for (int i = 0; i < len; i++) {
253 sbReceive.append(charBuffer[i]);
254 sb.append(charBuffer[i]);
256 appendToRouterFile("/tmp/" + routerName, sb);
257 if (listener != null) {
258 listener.receivedString(sb.toString());
260 log.debug("sb2={0} delimiters={1}", sb.toString(), delimeters);
261 if (sb.toString().contains("\nariPrompt>")) {
262 log.debug("Found ari prompt");
267 } catch (JSchException e) {
268 log.error("JSchException occurred", e);
269 throw new TimedOutException(e.getMessage());
270 } catch (IOException e) {
271 log.error("IOException occurred", e);
272 throw new TimedOutException(e.getMessage());
275 if (fileWriter != null) {
278 } catch (IOException ex) {
279 log.warn("Failed to close fileWriter output stream", ex);
282 return stripOffCmdFromRouterResponse(sbReceive.toString());
285 public boolean checkIfReceivedStringMatchesDelimeter(String delimeters, String receivedString,
286 String cmdThatWasSent) {
287 // The delimeters are in a '|' seperated string. Return true on the first match.
288 log.debug("Entered checkIfReceivedStringMatchesDelimeter: delimeters={0} cmdThatWasSent={1} receivedString={2}",
289 delimeters, cmdThatWasSent, receivedString);
290 StringTokenizer st = new StringTokenizer(delimeters, "|");
292 if ((delimeters.contains("#$")) || ("CLI".equals(routerCmdType))) // This would be an IOS XR, CLI command.
294 int x = receivedString.lastIndexOf('#');
295 int y = receivedString.length() - 1;
296 log.debug("IOS XR, CLI command");
297 if (log.isTraceEnabled()) {
298 log.trace("cmdThatWasSent={0}, lastIndexOf hash delimiter={1}, maxIndexNum={2}", cmdThatWasSent, x, y);
300 return (x != -1) && (y == x);
302 if (cmdThatWasSent.contains("show config")) {
303 log.trace("In the block for 'show config'");
304 while (st.hasMoreTokens()) {
305 String delimeter = st.nextToken();
306 // Make sure we don't get faked out by a response of " #".
308 // # signaling-local-address ipv6 FD00:F4D5:EA06:1::110:136:254
310 int x = receivedString.lastIndexOf(delimeter);
311 if ((receivedString.lastIndexOf(delimeter) != -1) && (receivedString.lastIndexOf(" #") != x - 1)) {
312 log.debug("receivedString={0}", receivedString);
313 log.trace("Found ending for 'show config' command, exiting.");
318 aggregatedReceivedString = aggregatedReceivedString + receivedString;
319 appendToFile("/tmp/aggregatedReceivedString.debug", aggregatedReceivedString);
321 log.debug("receivedString={0}", receivedString);
322 while (st.hasMoreTokens()) {
323 String delimeter = st.nextToken();
324 log.debug("Looking for an delimiter of:{0}", delimeter);
325 if (aggregatedReceivedString.indexOf(delimeter) != -1) {
326 log.debug("Found delimiter={0}, exiting", delimeter);
327 aggregatedReceivedString = "";
335 public boolean checkIfReceivedStringMatchesDelimeter(int len, String delimeter) {
338 String str = StringUtils.EMPTY;
340 if (jcraftReadSwConfigFileFromDisk()) {
341 log.trace("jcraftReadSwConfigFileFromDisk block");
342 File fileName = new File(routerFileName);
343 log.debug("jcraftReadSwConfigFileFromDisk::: Will read the tail end of the file from the disk");
345 str = getLastFewLinesOfFile(fileName, 3);
346 } catch (IOException e) {
347 log.warn("IOException occurred, while reading file=" + fileName, e);
350 // When looking at the end of the charBuffer, don't include any linefeeds or spaces. We only want to make the smallest string possible.
351 for (x = len - 1; x >= 0; x--) {
353 if ((c != 10) && (c != 32)) // Not a line feed nor a space.
358 if ((x + 1 - 13) >= 0) {
359 str = new String(charBuffer, x + 1 - 13, 13);
360 log.debug("str:{0}", str);
362 File fileName = new File(routerFileName);
363 log.debug("Will read the tail end of the file from the disk, x={0} len={1} str={2} routerFileName={3}",
364 x, len, str, routerFileName);
366 str = getLastFewLinesOfFile(fileName, 3);
367 } catch (IOException e) {
368 log.warn("IOException occurred, while reading file=" + fileName, e);
373 log.debug("Parsed string was str='{0}', searched delimiter was {1}");
374 return str.contains(delimeter);
377 public void closeConnection() {
378 log.info("Closing connection");
382 session.disconnect();
386 public void send(String cmd) throws IOException {
387 try (OutputStream os = channel.getOutputStream(); DataOutputStream dos = new DataOutputStream(os)) {
388 sendSshCommand(cmd, dos);
389 } catch (IOException e) {
390 log.error("IOException occurred while sending command=" + cmd, e);
395 public void sendChar(int v) throws IOException {
396 try (OutputStream os = channel.getOutputStream(); DataOutputStream dos = new DataOutputStream(os)) {
397 if (log.isTraceEnabled()) {
398 log.trace("Sending charCode: {0}", v);
402 } catch (IOException e) {
403 log.error("IOException occurred while writing char to channel output stream", e);
408 public void send(byte[] b, int off, int len) throws IOException {
409 try (OutputStream os = channel.getOutputStream(); DataOutputStream dos = new DataOutputStream(os)) {
410 dos.write(b, off, len);
412 } catch (IOException e) {
413 log.error("IOException occurred while writing bytes to channel output stream", e);
418 public static class MyUserInfo implements UserInfo, UIKeyboardInteractive {
421 public String getPassword() {
426 public boolean promptYesNo(String str) {
431 public String getPassphrase() {
436 public boolean promptPassphrase(String message) {
441 public boolean promptPassword(String message) {
446 public void showMessage(String message) {
451 public String[] promptKeyboardInteractive(String destination,
456 return new String[0];
460 public void addListener(TelnetListener listener) {
461 this.listener = listener;
464 private void appendToFile(String fileName, String dataToWrite) {
465 File outputFile = new File(fileName);
466 if (outputFile.exists()) {
467 try (FileWriter fw = new FileWriter(fileName, true); BufferedWriter ow = new BufferedWriter(fw)) {
468 ow.write(dataToWrite);
470 } catch (IOException e) {
471 log.error("IOException occurred while writing to file=" + fileName, e);
476 public String getTheDate() {
477 DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy H:mm:ss ");
478 return dateFormat.format(Calendar.getInstance().getTime());
482 public void appendToRouterFile(String fileName, StringBuilder dataToWrite) {
483 appendToFile(fileName, dataToWrite.toString());
486 public void appendToRouterFile(String fileName, int len) {
487 File outputFile = new File(fileName);
488 if (outputFile.exists()) {
489 try (FileWriter fw = new FileWriter(fileName, true); BufferedWriter ow = new BufferedWriter(fw)) {
490 ow.write(charBuffer, 0, len);
492 } catch (IOException e) {
493 log.error("IOException occurred while writing to router file=" + fileName, e);
498 public String removeWhiteSpaceAndNewLineCharactersAroundString(String str) {
499 if (str != null && !StringUtils.EMPTY.equals(str)) {
500 StringTokenizer strTok = new StringTokenizer(str, "\n");
501 StringBuilder sb = new StringBuilder();
503 while (strTok.hasMoreTokens()) {
504 String line = strTok.nextToken();
507 return sb.toString().trim();
509 return StringUtils.EMPTY;
512 public String stripOffCmdFromRouterResponse(String routerResponse) {
513 // The session of SSH will echo the command sent to the router, in the router's response.
514 // Since all our commands are terminated by a '\n', strip off the first line
515 // of the response from the router. This first line contains the orginal command.
516 StringTokenizer rr = new StringTokenizer(routerResponse, "\n");
517 StringBuilder sb = new StringBuilder();
519 int numTokens = rr.countTokens();
521 rr.nextToken(); //Skip the first line.
522 while (rr.hasMoreTokens()) {
523 sb.append(rr.nextToken()).append("\n");
526 return sb.toString();
529 public void setRouterCommandType(String type) {
530 this.routerCmdType = type;
531 log.debug("Router command type is set to: {0}", type);
534 public String getLastFewLinesOfFile(File file, int linesToRead) throws IOException {
535 RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r");
537 StringBuilder builder = new StringBuilder();
539 long length = file.length();
541 randomAccessFile.seek(length);
542 for (long seek = length; seek >= 0; --seek) {
543 randomAccessFile.seek(seek);
544 char c = (char) randomAccessFile.read();
547 builder = builder.reverse();
548 tail = builder.toString() + tail;
550 builder.setLength(0);
551 if (lines == linesToRead) {
556 randomAccessFile.close();
557 if (log.isDebugEnabled()) {
558 log.debug("Content read from file={0} was tail={1}", file.getName(), tail);
563 public boolean jcraftReadSwConfigFileFromDisk() {
564 return jcraftReadSwConfigFileFromDisk.exists();
567 public String getEquipNameCode() {
568 return equipNameCode;
571 public void setEquipNameCode(String equipNameCode) {
572 this.equipNameCode = equipNameCode;
575 public String getRouterName() {
579 // Routine does reads until it has read 'nchars' or times out.
580 public void receiveUntilBufferFlush(int ncharsSent, int timeout, String message) throws IOException {
581 log.debug("ncharsSent={0}, timeout={1}, message={2}", ncharsSent, timeout, message);
582 int ncharsTotalReceived = 0;
585 long deadline = new Date().getTime() + timeout;
588 session.setTimeout(timeout); // This is the socket timeout value.
590 if (new Date().getTime() > deadline) {
591 log.error("Routine has timed out: ncharsSent={0}, ncharsTotalReceived={1}", ncharsSent,
592 ncharsTotalReceived);
593 throw new TimedOutException("Routine has timed out");
595 ncharsRead = reader.read(charBuffer, 0, BUFFER_SIZE);
596 if (listener != null) {
597 listener.receivedString(String.copyValueOf(charBuffer, 0, ncharsRead));
599 appendToRouterFile("/tmp/" + routerName, ncharsRead);
600 ncharsTotalReceived = ncharsTotalReceived + ncharsRead;
601 if (ncharsTotalReceived >= ncharsSent) {
602 log.debug("Received the correct number of characters, ncharsSent={0}, ncharsTotalReceived={1}",
603 ncharsSent, ncharsTotalReceived);
608 } catch (JSchException e) {
609 log.error("JSchException occurred while command sending", e);
610 log.debug("ncharsSent={0}, ncharsTotalReceived={1}, ncharsRead={2} until error occurred",
611 ncharsSent, ncharsTotalReceived, ncharsRead);
612 throw new TimedOutException(e.getMessage());
616 public String getHostName() {
620 public String getUserName() {
624 public String getPassWord() {
628 public void sftpPutFile(String sourcePath, String destDirectory) throws IOException {
630 Session sftpSession = jsch.getSession(userName, hostName, 22);
631 UserInfo ui = new MyUserInfo();
632 sftpSession.setPassword(passWord);
633 sftpSession.setUserInfo(ui);
634 sftpSession.connect(30 * 1000);
635 ChannelSftp sftp = (ChannelSftp) sftpSession.openChannel("sftp");
637 log.debug("Sending via sftp from source: {0} to destination: {1}", sourcePath, destDirectory);
638 sftp.put(sourcePath, destDirectory, ChannelSftp.OVERWRITE);
639 sftpSession.disconnect();
640 } catch (JSchException ex) {
641 log.error("JSchException occurred while handling sftp session", ex);
642 throw new IOException(ex.getMessage());
643 } catch (SftpException ex) {
644 log.error("SftpException occurred during file transfer", ex);
645 throw new IOException(ex.getMessage());
649 public void sftpPutStringData(String stringOfData, String fullPathDest) throws IOException {
651 Session sftpSession = jsch.getSession(userName, hostName, 22);
652 UserInfo ui = new MyUserInfo();
653 sftpSession.setPassword(passWord);
654 sftpSession.setUserInfo(ui);
655 sftpSession.connect(30 * 1000);
656 ChannelSftp sftp = (ChannelSftp) sftpSession.openChannel("sftp");
658 InputStream is = new ByteArrayInputStream(stringOfData.getBytes());
659 log.debug("Sending via sftp stringOfData to destination: {0}", fullPathDest);
660 sftp.put(is, fullPathDest, ChannelSftp.OVERWRITE);
661 sftpSession.disconnect();
662 } catch (JSchException ex) {
663 log.error("JSchException occurred while handling sftp session", ex);
664 throw new IOException(ex.getMessage());
665 } catch (SftpException ex) {
666 log.error("SftpException occurred during data transfer", ex);
667 throw new IOException(ex.getMessage());
671 public String sftpGet(String fullFilePathName) throws IOException {
673 Session sftpSession = jsch.getSession(userName, hostName, 22);
674 UserInfo ui = new MyUserInfo();
675 sftpSession.setPassword(passWord);
676 sftpSession.setUserInfo(ui);
677 sftpSession.connect(30 * 1000);
678 ChannelSftp sftp = (ChannelSftp) sftpSession.openChannel("sftp");
680 InputStream in = sftp.get(fullFilePathName);
681 String sftpFileString = readInputStreamAsString(in);
682 log.debug("Received data via sftp connection sftpFileString={0} from fullFilePathName={1}",
683 sftpFileString, fullFilePathName);
684 sftpSession.disconnect();
685 return sftpFileString;
686 } catch (JSchException ex) {
687 log.error("JSchException occurred while handling sftp session", ex);
688 throw new IOException(ex.getMessage());
689 } catch (SftpException ex) {
690 log.error("SftpException occurred during data transfer", ex);
691 throw new IOException(ex.getMessage());
695 public static String readInputStreamAsString(InputStream in) throws IOException {
696 BufferedInputStream bis = new BufferedInputStream(in);
697 ByteArrayOutputStream buf = new ByteArrayOutputStream();
698 int result = bis.read();
699 while (result != -1) {
700 byte b = (byte) result;
704 return buf.toString();
708 public void logMemoryUsage() {
709 int mb = 1024 * 1024;
711 long maxMemoryAvailable;
712 long memoryLeftOnHeap;
713 maxMemoryAvailable =runtime.maxMemory() / mb;
714 usedMemory = (runtime.totalMemory() / mb) - (runtime.freeMemory() / mb);
715 memoryLeftOnHeap = maxMemoryAvailable - usedMemory;
716 log.info("Memory usage: maxMemoryAvailable={0}, usedMemory={1}, memoryLeftOnHeap={2}",
717 maxMemoryAvailable, usedMemory, memoryLeftOnHeap);
720 // User specifies the port number, and the subsystem
721 public void connect(String hostname, String username, String password, String prompt, int timeOut, int portNum,
722 String subsystem) throws IOException {
724 if (log.isDebugEnabled()) {
726 "Attempting to connect to {0} username={1} prompt='{2}' timeOut={3} portNum={4} subsystem={5}",
727 hostname, username, prompt, timeOut, portNum, subsystem);
729 routerName = hostname;
732 session = jsch.getSession(username, hostname, portNum);
733 UserInfo ui = new MyUserInfo();
734 session.setPassword(password);
735 session.setUserInfo(ui);
736 session.setConfig("StrictHostKeyChecking", "no");
737 session.connect(timeOut);
738 session.setServerAliveCountMax(
739 0); // If this is not set to '0', then socket timeout on all reads will not work!!!!
740 channel = session.openChannel("subsystem");
741 ((ChannelSubsystem) channel).setSubsystem(subsystem);
742 ((ChannelSubsystem) channel).setPty(true); //expected ptyType vt102
744 inputStream = channel.getInputStream();
745 dis = new DataInputStream(inputStream);
746 reader = new BufferedReader(new InputStreamReader(dis), BUFFER_SIZE);
747 channel.connect(5000);
748 } catch (JSchException e) {
749 log.error("JschException occurred ", e);
750 throw new IOException(e.getMessage());
751 } catch (TimedOutException e) {
752 log.error("TimedOutException occurred", e);
753 throw new IOException(e.getMessage());
757 public void connect(String hostName, String username, String password, int portNumber) throws IOException {
759 log.debug("Attempting to connect to {0} username={1} portNumber={2}", hostName, username, portNumber);
760 routerName = hostName;
761 this.hostName = hostName;
765 java.util.Properties config = new java.util.Properties();
766 config.put("StrictHostKeyChecking", "no");
767 session = jsch.getSession(username, hostName, 22);
768 UserInfo ui = new MyUserInfo();
769 session.setConfig(config);
770 session.setPassword(password);
771 session.setUserInfo(ui);
772 session.connect(30000);
773 channel = session.openChannel("shell");
774 session.setServerAliveCountMax(
775 0); // If this is not set to '0', then socket timeout on all reads will not work!!!!
776 ((ChannelShell) channel).setPtyType("vt102");
777 inputStream = channel.getInputStream();
778 dis = new DataInputStream(inputStream);
779 reader = new BufferedReader(new InputStreamReader(dis), BUFFER_SIZE);
782 receiveUntil(":~#", 9000, "No cmd was sent, just waiting, but we can stop on a '~#'");
783 } catch (Exception e) {
784 log.warn("Caught an Exception: Nothing to flush out.", e);
787 } catch (JSchException e) {
788 log.error("JschException occurred ", e);
789 throw new IOException(e.getMessage());
794 public void put(String sourcePath, String destDirectory) throws IOException {
796 Session sftpSession = jsch.getSession(userName, hostName, 22);
797 UserInfo ui = new MyUserInfo();
798 sftpSession.setPassword(passWord);
799 sftpSession.setUserInfo(ui);
800 sftpSession.connect(30 * 1000);
801 ChannelSftp sftp = (ChannelSftp) sftpSession.openChannel("sftp");
803 log.debug("Sending via sftp from source: {0} to destination: {1}", sourcePath, destDirectory);
804 sftp.put(sourcePath, destDirectory, ChannelSftp.OVERWRITE);
805 sftpSession.disconnect();
806 } catch (JSchException ex) {
807 log.error("JSchException occurred while handling sftp session", ex);
808 throw new IOException(ex.getMessage());
809 } catch (SftpException ex) {
810 log.error("SftpException occurred during file transfer", ex);
811 throw new IOException(ex.getMessage());
815 public void put(InputStream is, String fullPathDest, String hostName, String userName, String passWord)
817 Session sftpSession = null;
819 log.debug("Sftp put invoked, connection details: username={1} hostname={2}",
822 java.util.Properties config = new java.util.Properties();
823 config.put("StrictHostKeyChecking", "no");
824 sftpSession = jsch.getSession(userName, hostName, 22);
825 UserInfo ui = new MyUserInfo();
826 sftpSession.setPassword(passWord);
827 sftpSession.setUserInfo(ui);
828 sftpSession.setConfig(config);
829 sftpSession.connect(30 * 1000);
830 ChannelSftp sftp = (ChannelSftp) sftpSession.openChannel("sftp");
832 String oldFiles = fullPathDest + "*";
833 log.debug("Deleting old files: {0}", oldFiles);
836 } catch (SftpException ex) {
837 String exp = "No such file";
838 if (ex.getMessage() != null && ex.getMessage().contains(exp)) {
839 log.warn("No files found, continue");
841 log.error("SftpException while invoking rm command over sftp", ex);
845 log.debug("Sending stringOfData to destination {0}", fullPathDest);
846 sftp.put(is, fullPathDest, ChannelSftp.OVERWRITE);
847 } catch (JSchException ex) {
848 log.error("JSchException occurred while handling sftp session", ex);
849 throw new IOException(ex.getMessage());
850 } catch (SftpException ex) {
851 log.error("SftpException occurred during file transfer", ex);
852 throw new IOException(ex.getMessage());
854 if (sftpSession != null) {
855 sftpSession.disconnect();
861 public String get(String fullFilePathName, String hostName, String userName, String passWord) throws IOException {
862 Session sftpSession = null;
864 log.debug("Sftp get invoked, connection details: username={1} hostname={2}",
867 sftpSession = jsch.getSession(userName, hostName, 22);
868 java.util.Properties config = new java.util.Properties();
869 config.put("StrictHostKeyChecking", "no");
870 UserInfo ui = new MyUserInfo();
871 sftpSession.setPassword(passWord);
872 sftpSession.setUserInfo(ui);
873 sftpSession.setConfig(config);
874 sftpSession.connect(30 * 1000);
875 ChannelSftp sftp = (ChannelSftp) sftpSession.openChannel("sftp");
877 InputStream in = sftp.get(fullFilePathName);
878 return readInputStreamAsString(in);
879 } catch (JSchException ex) {
880 log.error("JSchException occurred while handling sftp session", ex);
881 throw new IOException(ex.getMessage());
882 } catch (SftpException ex) {
883 log.error("SftpException occurred during file transfer", ex);
884 throw new IOException(ex.getMessage());
886 if (sftpSession != null) {
887 sftpSession.disconnect();
892 public String send(String cmd, String delimiter) throws IOException {
893 try (OutputStream os = channel.getOutputStream(); DataOutputStream dos = new DataOutputStream(os)) {
894 sendSshCommand(cmd, dos);
895 return receiveUntil(delimiter, 300000, cmd);
896 } catch (IOException ex) {
897 log.error("IOException occurred", ex);
898 throw new IOException(ex.getMessage());
902 private void sendSshCommand(@Nonnull String originalCommand, @Nonnull DataOutputStream channelOutputStream)
904 String command = enhanceCommandWithEOL(originalCommand);
905 int length = command.length(); // 2,937,706
906 int charsChunkSize = 300000;
907 int charsTotalSent = 0;
909 log.debug("Sending ssh command: length={0}, payload: {1}", length, command);
910 if (isCmdLengthEnoughToSendInChunks(length, charsChunkSize)) {
912 for (int i = 0; i < length; i += charsChunkSize) {
913 String commandChunk = command.substring(i, Math.min(length, i + charsChunkSize));
914 int numCharsSentInChunk = commandChunk.length();
915 charsTotalSent = charsTotalSent + commandChunk.length();
916 log.debug("Iteration nr:{0}, sending command chunk: {1}", i, numCharsSentInChunk);
917 channelOutputStream.writeBytes(commandChunk);
918 channelOutputStream.flush();
920 if (numCharsSentInChunk < length) {
921 receiveUntilBufferFlush(numCharsSentInChunk, timeout, "buffer flush i=" + i);
923 log.trace("i={0}, flush immediately", i);
924 channelOutputStream.flush();
926 } catch (IOException ex) {
927 log.warn("IOException occurred: nothing to flush out", ex);
931 channelOutputStream.writeBytes(command);
933 channelOutputStream.flush();
936 private boolean isCmdLengthEnoughToSendInChunks(int length, int chunkSize) {
937 return length > 2 * chunkSize;
940 private String enhanceCommandWithEOL(@Nonnull String originalCommand) {
941 char commandEnding = originalCommand.charAt(originalCommand.length() - 1);
942 if (commandEnding != '\n' && commandEnding != '\r') {
943 return originalCommand + "\n";
945 return originalCommand;