/* ************************************************************************ # # DivConq # # http://divconq.com/ # # Copyright: # Copyright 2014 eTimeline, LLC. All rights reserved. # # License: # See the license.txt file in the project's top-level directory for details. # # Authors: # * Andy White # ************************************************************************ */ package divconq.interchange.ssh; public class SftpDriver { /*extends RecordStruct implements IFileStoreDriver { protected String password = null; protected String passphrase = null; protected Session session = null; protected CallbackQueue<ChannelSftp> channels = null; @Override public void setMimeProvider(IMimeProvider v) { // TODO Auto-generated method stub } public SftpDriver() { this.setField("Scanner", new SftpScanner(this)); this.setField("RootFolder", "."); this.channels = new CallbackQueue<ChannelSftp>(); this.channels.setWatcher(this.channels.new QueueWatcher() { @Override public void disposed(ChannelSftp res) { res.exit(); } }); } @Override protected void doCopy(Struct n) { super.doCopy(n); //FileSystemDriver nn = (FileSystemDriver)n; //nn.cwd = this.cwd; } @Override public Struct deepCopy() { SftpDriver cp = new SftpDriver(); this.doCopy(cp); return cp; } @Override public void dispose() { this.close(null); super.dispose(); } /* @Override public void toBuilder(ICompositeBuilder builder) throws BuilderStateException { builder.startRecord(); for (FieldStruct f : this.fields.values()) f.toBuilder(builder); // TODO add in FS specific fields builder.endRecord(); } @Override public Struct select(PathPart... path) { if (path.length > 0) { PathPart part = path[0]; if (part.isField()) { String fld = part.getField(); if ("Scanner".equals(fld)) return this.search; } } return super.select(path); } * / @Override public void connect(RecordStruct params, OperationCallback callback) { // TODO clean and start new this.channels.dispose() if (this.session != null) { this.session.disconnect(); this.session = null; } try { JSch jsch = new JSch(); String host = this.getFieldAsString("Host"); Long pt = this.getFieldAsInteger("Port"); int port = (pt == null) ? 22 : pt.intValue(); String user = this.getFieldAsString("User"); this.password = this.getFieldAsString("Password"); this.passphrase = this.getFieldAsString("Passphrase"); // TODO /* String keyfile = this.getFieldAsString("Key"); if (StringUtil.isNotBlank(keyfile)) jsch.addIdentity(keyfile, Sftp.passphrase); * / this.session = jsch.getSession(user, host, port); // username and password will be given via UserInfo interface. UserInfo ui = new MyUserInfo(); this.session.setUserInfo(ui); this.session.connect(); Channel channel = this.session.openChannel("sftp"); channel.connect(); if (this.hasField("RootFolder")) ((ChannelSftp) channel).cd(this.getFieldAsString("RootFolder"));; this.setField("RootFolder", ((ChannelSftp) channel).pwd()); this.channels.add((ChannelSftp) channel); } catch (Exception x) { // TODO } if (callback == null) return; System.out.println("cwd: " + this.getFieldAsString("RootFolder")); callback.completed(); } @Override public void close(OperationCallback callback) { this.channels.dispose(); if (this.session != null) { this.session.disconnect(); this.session = null; } if (callback == null) return; callback.completed(); } public void getChannel(FuncCallback<ChannelSftp> callback) { this.channels.pop(callback); } public void releaseChannel(ChannelSftp channel) { this.channels.add(channel); } @Override public void operation(final StackEntry stack, final XElement codeEl) { if ("Connect".equals(codeEl.getName())) { this.connect(null, new OperationCallback() { @Override public void callback() { stack.resume(); } }); return; } if ("Close".equals(codeEl.getName())) { this.close(new OperationCallback() { @Override public void callback() { stack.resume(); } }); return; } if ("Put".equals(codeEl.getName())) { // TODO integrate with put method below Struct src = stack.refFromElement(codeEl, "Source"); if (!(src instanceof IFileStoreFile) && ! (src instanceof RecordStruct)) { // TODO log wrong type stack.resume(); return; } boolean relative = stack.boolFromElement(codeEl, "Relative", true); this.put((IFileStoreFile)src, relative, new FuncCallback<IFileStoreFile>() { @Override public void callback() { // TODO check errors String handle = stack.stringFromElement(codeEl, "Handle"); if (handle != null) stack.addVariable(handle, (Struct) this.getResult()); stack.resume(); } }); return; } if ("PutAll".equals(codeEl.getName())) { // TODO integrate with put method below Struct src = stack.refFromElement(codeEl, "Source"); if (!(src instanceof IItemCollection)) { // TODO log wrong type stack.resume(); return; } boolean relative = stack.boolFromElement(codeEl, "Relative", true); this.putAll((IItemCollection)src, relative, new OperationCallback() { @Override public void callback() { // TODO check errors System.out.println("done"); stack.resume(); } }); return; } /* if ("GetInfo".equals(codeEl.getName())) { String path = stack.stringFromElement(codeEl, "Path"); if (StringUtil.isEmpty(path)) { // TODO log missing stack.resume(); return; } String handle = stack.stringFromElement(codeEl, "Handle"); if (handle != null) stack.addVariable(handle, new SftpFile(SftpDriver.this, new RecordStruct(new FieldStruct("Path", path)))); stack.resume(); return; } if ("Put".equals(codeEl.getName())) { Struct src = stack.refFromElement(codeEl, "Source"); if (src == null) { // TODO log missing stack.resume(); return; } if (!(src instanceof IFileStoreFile) && ! (src instanceof RecordStruct)) { // TODO log wrong type stack.resume(); return; } RecordStruct rsrc = (RecordStruct)src; final IFileStoreFile ssrc = (IFileStoreFile)src; boolean relative = stack.boolFromElement(codeEl, "Relative", true); String cwd = this.getFieldAsString("RootFolder"); String dfilepath = cwd + "/" + (relative ? rsrc.getFieldAsString("Path") : rsrc.getFieldAsString("Name")); System.out.println("copied to: " + dfilepath); final File dest = new File(dfilepath); dest.getParentFile().mkdirs(); try { final FileOutputStream out = new FileOutputStream(dest); ssrc.copyTo(out, new OperationCallback() { @Override public void callback() { // TODO improve, check abort, etc try { out.close(); } catch (IOException x) { } String handle = stack.stringFromElement(codeEl, "Handle"); if (handle != null) stack.addVariable(handle, new SftpFile(SftpDriver.this, dest)); stack.resume(); } }); return; } catch (Exception x) { // TODO //ssrc.abort(); } stack.resume(); return; } * / /* if ("ChangeDirectory".equals(code.getName())) { String path = stack.stringFromElement(code, "Path"); if (StringUtil.isEmpty(path)) { // TODO log stack.resume(); return; } this.cwd = new File(path); stack.resume(); return; } if ("ScanFilter".equals(code.getName())) { String path = stack.stringFromElement(code, "Path"); ... if (StringUtil.isEmpty(path)) { // TODO log stack.resume(); return; } this.cwd = new File(path); stack.resume(); return; } * / //System.out.println("fs operation: " + code); super.operation(stack, codeEl); } @Override public IFileStoreFile getFile(RecordStruct file) { return null; // TODO new SftpFile(this, file); } public class MyUserInfo implements UserInfo { public String getPassword() { return SftpDriver.this.password; } public boolean promptYesNo(String str) { return true; } public String getPassphrase() { return SftpDriver.this.passphrase; } public boolean promptPassphrase(String message) { return true; } public boolean promptPassword(String message) { return true; } public void showMessage(String message) { System.out.println(message); // TODO } } @Override public void getFileDetail(String path, FuncCallback<IFileStoreFile> callback) { // TODO Auto-generated method stub } @Override public void getRootFolder(FuncCallback<String> callback) { // TODO Auto-generated method stub } @Override public void setRootFolder(String path, OperationCallback callback) { // TODO Auto-generated method stub } @Override public void addFolder(String path, OperationCallback callback) { // TODO Auto-generated method stub } @Override public void removeFolder(String path, OperationCallback callback) { // TODO Auto-generated method stub } @Override public void queryFeatures(FuncCallback<RecordStruct> callback) { // TODO Auto-generated method stub } @Override public void customCommand(RecordStruct params, FuncCallback<RecordStruct> callback) { // TODO Auto-generated method stub } @Override public IFileStoreScanner getScanner() { // TODO Auto-generated method stub return null; } @Override public void getFolderListing(String path, FuncCallback<List<IFileStoreFile>> callback) { // TODO Auto-generated method stub } @Override public void getFolderListing2(String path, FuncCallback<ListStruct> callback) { // TODO Auto-generated method stub } @Override public void put(IFileStoreFile source, boolean relative, final FuncCallback<IFileStoreFile> callback) { if (source == null) { // TODO log missing callback.completed(); return; } if (! (source instanceof RecordStruct)) { // TODO log wrong type callback.completed(); return; } RecordStruct rsrc = (RecordStruct)source; String cwd = this.getFieldAsString("RootFolder"); final String dfilepath = cwd + "/" + (relative ? rsrc.getFieldAsString("Path") : rsrc.getFieldAsString("Name")); int pos = dfilepath.lastIndexOf('/'); final String dfileparent = dfilepath.substring(0, pos); source.getInputStream(new FuncCallback<InputStream>() { @Override public void callback() { final InputStream in = this.getResult(); SftpDriver.this.getChannel(new FuncCallback<ChannelSftp>() { @Override public void callback() { ChannelSftp channel = this.getResult(); try { System.out.println("copied to sftp: " + dfilepath); // TODO mkdirs // dest.getParentFile().mkdirs(); channel.mkdir(dfileparent); channel.put(in, dfilepath); @SuppressWarnings("rawtypes") Vector flist = channel.ls(dfilepath); if (flist.size() < 1) { // TODO log } else { LsEntry entry = (LsEntry)flist.get(0); callback.setResult(new SftpFile(SftpDriver.this, entry, dfilepath)); } callback.completed(); } catch (Exception x) { // TODO //ssrc.abort(); callback.completed(); } finally { SftpDriver.this.releaseChannel(channel); } } }); } }); } @Override public void putAll(IItemCollection files, boolean relative, OperationCallback callback) { // TODO Auto-generated method stub } @Override public void put(InputStream in, long size, IFileStoreFile dest, boolean relative, OperationCallback callback) { // TODO Auto-generated method stub } */ }