Java tutorial
/*! ****************************************************************************** * * Pentaho Data Integration * * Copyright (C) 2002-2013 by Pentaho : http://www.pentaho.com * ******************************************************************************* * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ******************************************************************************/ package org.pentaho.di.trans.steps.sftpscan.client; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Vector; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.vfs.FileObject; import org.apache.commons.vfs.FileType; import org.apache.commons.vfs.FileUtil; import org.pentaho.di.core.Const; import org.pentaho.di.core.exception.KettleException; import org.pentaho.di.core.exception.KettleFileException; import org.pentaho.di.core.exception.KettleJobException; import org.pentaho.di.core.vfs.KettleVFS; import com.jcraft.jsch.Channel; import com.jcraft.jsch.ChannelSftp; import com.jcraft.jsch.ChannelSftp.LsEntry; import com.jcraft.jsch.JSch; import com.jcraft.jsch.JSchException; import com.jcraft.jsch.Proxy; import com.jcraft.jsch.ProxyHTTP; import com.jcraft.jsch.ProxySOCKS5; import com.jcraft.jsch.Session; import com.jcraft.jsch.SftpATTRS; import com.jcraft.jsch.SftpException; public class SFTPClient { private static final String COMPRESSION_S2C = "compression.s2c"; private static final String COMPRESSION_C2S = "compression.c2s"; public static final String PROXY_TYPE_SOCKS5 = "SOCKS5"; public static final String PROXY_TYPE_HTTP = "HTTP"; public static final String HTTP_DEFAULT_PORT = "80"; public static final String SOCKS5_DEFAULT_PORT = "1080"; public static final int SSH_DEFAULT_PORT = 22; private InetAddress serverIP; private int serverPort; private String userName; private String password; private String prvkey = null; // Private key private String passphrase = null; // Empty passphrase for now private String compression = null; private Session s; private ChannelSftp c; /** * Init Helper Class with connection settings * * @param serverIP * IP address of remote server * @param serverPort * port of remote server * @param userName * username of remote server * @throws KettleJobException */ public SFTPClient(InetAddress serverIP, int serverPort, String userName) throws KettleJobException { this(serverIP, serverPort, userName, null, null); } /** * Init Helper Class with connection settings * * @param serverIP * IP address of remote server * @param serverPort * port of remote server * @param userName * username of remote server * @param privateKeyFilename * filename of private key * @throws KettleJobException */ public SFTPClient(InetAddress serverIP, int serverPort, String userName, String privateKeyFilename) throws KettleJobException { this(serverIP, serverPort, userName, privateKeyFilename, null); } /** * Init Helper Class with connection settings * * @param serverIP * IP address of remote server * @param serverPort * port of remote server * @param userName * username of remote server * @param privateKeyFilename * filename of private key * @param passPhrase * passphrase * @throws KettleJobException */ public SFTPClient(InetAddress serverIP, int serverPort, String userName, String privateKeyFilename, String passPhrase) throws KettleJobException { if (serverIP == null || serverPort < 0 || userName == null || userName.equals("")) { throw new KettleJobException( "For a SFTP connection server name and username must be set and server port must be greater than zero."); } this.serverIP = serverIP; this.serverPort = serverPort; this.userName = userName; JSch jsch = new JSch(); try { if (!Const.isEmpty(privateKeyFilename)) { // We need to use private key authentication this.prvkey = privateKeyFilename; byte[] passphrasebytes = new byte[0]; if (!Const.isEmpty(passPhrase)) { // Set passphrase this.passphrase = passPhrase; passphrasebytes = GetPrivateKeyPassPhrase().getBytes(); } jsch.addIdentity(getUserName(), FileUtil.getContent(KettleVFS.getFileObject(prvkey)), // byte[] privateKey null, // byte[] publicKey passphrasebytes); // byte[] passPhrase } s = jsch.getSession(userName, serverIP.getHostAddress(), serverPort); } catch (IOException e) { throw new KettleJobException(e); } catch (KettleFileException e) { throw new KettleJobException(e); } catch (JSchException e) { throw new KettleJobException(e); } } public void login(String password) throws KettleJobException { this.password = password; s.setPassword(this.getPassword()); try { java.util.Properties config = new java.util.Properties(); config.put("StrictHostKeyChecking", "no"); // set compression property // zlib, none String compress = getCompression(); if (compress != null) { config.put(COMPRESSION_S2C, compress); config.put(COMPRESSION_C2S, compress); } s.setConfig(config); s.connect(); Channel channel = s.openChannel("sftp"); channel.connect(); c = (ChannelSftp) channel; } catch (JSchException e) { throw new KettleJobException(e); } } public void chdir(String dirToChangeTo) throws KettleJobException { try { c.cd(dirToChangeTo); } catch (SftpException e) { throw new KettleJobException(e); } } public String[] dir() throws KettleJobException { String[] fileList = null; try { java.util.Vector<?> v = c.ls("."); java.util.Vector<String> o = new java.util.Vector<String>(); if (v != null) { for (int i = 0; i < v.size(); i++) { Object obj = v.elementAt(i); if (obj != null && obj instanceof LsEntry) { LsEntry lse = (LsEntry) obj; if (!lse.getAttrs().isDir()) { o.add(lse.getFilename()); } } } } if (o.size() > 0) { fileList = new String[o.size()]; o.copyInto(fileList); } } catch (SftpException e) { throw new KettleJobException(e); } return fileList; } @SuppressWarnings("unchecked") public List<RemoteFile> ls(String remoteFolder, String wildcard, boolean recursive) throws KettleException { List<RemoteFile> fileList = new ArrayList<>(); Pattern pattern = null; if (!(wildcard == null) && wildcard.length() > 0) //sanity check pattern = Pattern.compile(wildcard); try { Vector<LsEntry> v = c.ls(remoteFolder); for (LsEntry lse : v) { if (!lse.getAttrs().isDir()) { if (pattern == null) { //no pattern, give me all you have fileList.add(buildRemoteFile(remoteFolder, lse)); } else { //filter the file list Matcher matcher = pattern.matcher(lse.getFilename()); if (matcher.matches()) fileList.add(buildRemoteFile(remoteFolder, lse)); } } else if (recursive && (!".".equals(lse.getFilename()) && !"..".equals(lse.getFilename()))) { fileList.addAll(ls(remoteFolder + "/" + lse.getFilename(), wildcard, true)); } } } catch (SftpException e) { throw new KettleException(e); } return fileList; } private RemoteFile buildRemoteFile(String currentFolder, LsEntry lse) { RemoteFile rf = new RemoteFile(); rf.setPath(currentFolder); rf.setName(lse.getFilename()); rf.setPermissions(Integer.toOctalString(lse.getAttrs().getPermissions() & 07777)); rf.setSize(lse.getAttrs().getSize()); rf.setUid(lse.getAttrs().getUId()); rf.setGid(lse.getAttrs().getGId()); rf.setAccessDate(new Date(lse.getAttrs().getATime() * 1000L)); rf.setModificationDate(new Date(lse.getAttrs().getMTime() * 1000L)); return rf; } public void get(FileObject localFile, String remoteFile) throws KettleJobException { OutputStream localStream = null; try { localStream = KettleVFS.getOutputStream(localFile, false); c.get(remoteFile, localStream); } catch (SftpException e) { throw new KettleJobException(e); } catch (IOException e) { throw new KettleJobException(e); } finally { if (localStream != null) { try { localStream.close(); } catch (IOException ignore) { // Ignore any IOException, as we're trying to close the stream anyways } } } } @Deprecated public void get(String localFilePath, String remoteFile) throws KettleJobException { int mode = ChannelSftp.OVERWRITE; try { c.get(remoteFile, localFilePath, null, mode); } catch (SftpException e) { throw new KettleJobException(e); } } public String pwd() throws KettleJobException { try { return c.pwd(); } catch (SftpException e) { throw new KettleJobException(e); } } public void put(FileObject fileObject, String remoteFile) throws KettleJobException { int mode = ChannelSftp.OVERWRITE; InputStream inputStream = null; try { inputStream = KettleVFS.getInputStream(fileObject); c.put(inputStream, remoteFile, null, mode); } catch (Exception e) { throw new KettleJobException(e); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { throw new KettleJobException(e); } } } } public void put(InputStream inputStream, String remoteFile) throws KettleJobException { int mode = ChannelSftp.OVERWRITE; try { c.put(inputStream, remoteFile, null, mode); } catch (Exception e) { throw new KettleJobException(e); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { throw new KettleJobException(e); } } } } public void delete(String file) throws KettleJobException { try { c.rm(file); } catch (SftpException e) { throw new KettleJobException(e); } } /** * Creates this file as a folder. */ public void createFolder(String foldername) throws KettleJobException { try { c.mkdir(foldername); } catch (SftpException e) { throw new KettleJobException(e); } } /** * Rename the file. */ public void renameFile(String sourcefilename, String destinationfilename) throws KettleJobException { try { c.rename(sourcefilename, destinationfilename); } catch (SftpException e) { throw new KettleJobException(e); } } public FileType getFileType(String filename) throws KettleJobException { try { SftpATTRS attrs = c.stat(filename); if (attrs == null) { return FileType.IMAGINARY; } if ((attrs.getFlags() & SftpATTRS.SSH_FILEXFER_ATTR_PERMISSIONS) == 0) { throw new KettleJobException("Unknown permissions error"); } if (attrs.isDir()) { return FileType.FOLDER; } else { return FileType.FILE; } } catch (Exception e) { throw new KettleJobException(e); } } public boolean folderExists(String foldername) { boolean retval = false; try { SftpATTRS attrs = c.stat(foldername); if (attrs == null) { return false; } if ((attrs.getFlags() & SftpATTRS.SSH_FILEXFER_ATTR_PERMISSIONS) == 0) { throw new KettleJobException("Unknown permissions error"); } retval = attrs.isDir(); } catch (Exception e) { // Folder can not be found! } return retval; } public void setProxy(String host, String port, String user, String pass, String proxyType) throws KettleJobException { if (Const.isEmpty(host) || Const.toInt(port, 0) == 0) { throw new KettleJobException( "Proxy server name must be set and server port must be greater than zero."); } Proxy proxy = null; String proxyhost = host + ":" + port; if (proxyType.equals(PROXY_TYPE_HTTP)) { proxy = new ProxyHTTP(proxyhost); if (!Const.isEmpty(user)) { ((ProxyHTTP) proxy).setUserPasswd(user, pass); } } else if (proxyType.equals(PROXY_TYPE_SOCKS5)) { proxy = new ProxySOCKS5(proxyhost); if (!Const.isEmpty(user)) { ((ProxySOCKS5) proxy).setUserPasswd(user, pass); } } s.setProxy(proxy); } public void disconnect() { if (c != null) { c.disconnect(); } if (s != null) { s.disconnect(); } } public String GetPrivateKeyFileName() { return this.prvkey; } public String GetPrivateKeyPassPhrase() { return this.passphrase; } public String getPassword() { return password; } public int getServerPort() { return serverPort; } public String getUserName() { return userName; } public InetAddress getServerIP() { return serverIP; } public void setCompression(String compression) { this.compression = compression; } public String getCompression() { if (this.compression == null) { return null; } if (this.compression.equals("none")) { return null; } return this.compression; } }