/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package net.sf.jftp.net.wrappers;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StreamTokenizer;
import java.util.Date;
import java.util.Vector;
import net.sf.jftp.config.Settings;
import net.sf.jftp.net.BasicConnection;
import net.sf.jftp.net.ConnectionListener;
import net.sf.jftp.net.DataConnection;
import net.sf.jftp.net.FtpConnection;
import net.sf.jftp.system.StringUtils;
import net.sf.jftp.system.logging.Log;
import com.sun.xfile.XFile;
import com.sun.xfile.XFileInputStream;
import com.sun.xfile.XFileOutputStream;
public class NfsConnection implements BasicConnection
{
public static int buffer = 128000;
private String url = "";
private String host = "";
private String path = "";
private String pwd = "";
private Vector listeners = new Vector();
private String[] files;
private String[] size = new String[0];
private int[] perms = null;
//private NfsHandler handler = new NfsHandler();
private String baseFile;
private int fileCount;
private boolean isDirUpload = false;
private boolean shortProgress = false;
private boolean dummy = false;
public NfsConnection(String url)
{
this.url = url;
host = url.substring(6);
int x = host.indexOf("/");
if(x >= 0)
{
host = host.substring(0, x);
}
Log.out("nfs host is: " + host);
}
public boolean login(String user, String pass)
{
Log.out("nfs login called: " + url);
try
{
XFile xf = new XFile(url);
if(xf.exists())
{
Log.out("nfs url ok");
}
else
{
Log.out("WARNING: nfs url not found, cennection will fail!");
}
com.sun.nfs.XFileExtensionAccessor nfsx = (com.sun.nfs.XFileExtensionAccessor) xf.getExtensionAccessor();
//Log.out("nfs extension accessor: " + nfsx);
if(!nfsx.loginPCNFSD(host, user, pass))
{
Log.out("login failed!");
return false;
}
else
{
Log.debug("Login successful...");
}
}
catch(Exception e)
{
e.printStackTrace();
}
return true;
}
public String[] getExports() throws Exception
{
XFile xf = new XFile(url);
com.sun.nfs.XFileExtensionAccessor nfsx = (com.sun.nfs.XFileExtensionAccessor) xf.getExtensionAccessor();
String[] tmp = nfsx.getExports();
if(tmp == null)
{
return new String[0];
}
for(int i = 0; i < tmp.length; i++)
{
Log.out("nfs export found: " + tmp[i]);
}
return tmp;
}
public int removeFileOrDir(String file)
{
try
{
String tmp = toNFS(file);
XFile f = new XFile(tmp);
if(!f.getAbsolutePath().equals(f.getCanonicalPath()))
{
Log.debug("WARNING: Skipping symlink, remove failed.");
Log.debug("This is necessary to prevent possible data loss when removing those symlinks.");
return -1;
}
if(f.exists() && f.isDirectory())
{
cleanLocalDir(tmp);
}
//System.out.println(tmp);
if(!f.delete())
{
return -1;
}
else
{
return 1;
}
}
catch(IOException ex)
{
Log.debug("Error: " + ex.toString());
ex.printStackTrace();
}
return -1;
}
private void cleanLocalDir(String dir)
{
dir = toNFS(dir);
if(dir.endsWith("\\"))
{
Log.out("need to fix \\-problem!!!");
}
if(!dir.endsWith("/"))
{
dir = dir + "/";
}
//String remoteDir = StringUtils.removeStart(dir,path);
//System.out.println(">>> " + dir);
XFile f2 = new XFile(dir);
String[] tmp = f2.list();
if(tmp == null)
{
return;
}
for(int i = 0; i < tmp.length; i++)
{
XFile f3 = new XFile(dir + tmp[i]);
if(f3.isDirectory())
{
//System.out.println(dir);
cleanLocalDir(dir + tmp[i]);
f3.delete();
}
else
{
//System.out.println(dir+tmp[i]);
f3.delete();
}
}
}
public void sendRawCommand(String cmd)
{
}
public void disconnect()
{
}
public boolean isConnected()
{
return true;
}
public String getPWD()
{
String tmp = toNFS(pwd);
if(!tmp.endsWith("/"))
{
tmp = tmp + "/";
}
return tmp;
}
public boolean cdup()
{
String tmp = pwd;
if(pwd.endsWith("/") && !pwd.equals("nfs://"))
{
tmp = pwd.substring(0, pwd.lastIndexOf("/"));
}
return chdir(tmp.substring(0, tmp.lastIndexOf("/") + 1));
}
public boolean mkdir(String dirName)
{
if(!dirName.endsWith("/"))
{
dirName = dirName + "/";
}
dirName = toNFS(dirName);
File f = new File(dirName);
boolean x = f.mkdir();
fireDirectoryUpdate();
return x;
}
public void list() throws IOException
{
}
public boolean chdir(String p)
{
return chdir(p, true);
}
public boolean chdir(String p, boolean refresh)
{
if(p.endsWith(".."))
{
return cdup();
}
String tmp = toNFS(p);
if(!tmp.endsWith("/"))
{
tmp = tmp + "/";
}
if(check(tmp) < 3)
{
return false;
}
pwd = tmp;
if(refresh)
{
fireDirectoryUpdate();
}
return true;
}
private int check(String url)
{
int x = 0;
for(int j = 0; j < url.length(); j++)
{
if(url.charAt(j) == '/')
{
x++;
}
}
return x;
}
public boolean chdirNoRefresh(String p)
{
/*
String p2 = toNFS(p);
if(p2 == null) return false;
pwd = p2;
return true;
*/
return chdir(p, false);
}
public String getLocalPath()
{
//System.out.println("local: " + path);
return path;
}
private String toNFS(String f)
{
String file;
if(f.lastIndexOf("nfs://") > 0)
{
f = f.substring(f.lastIndexOf("nfs://"));
}
if(f.startsWith("nfs://"))
{
file = f;
}
else
{
file = getPWD() + f;
}
file = file.replace('\\', '/');
Log.out("nfs url: " + file);
return file;
}
public boolean setLocalPath(String p)
{
if(!p.startsWith("/") && !p.startsWith(":", 1))
{
p = path + p;
}
File f = new File(p);
if(f.exists())
{
try
{
path = f.getCanonicalPath();
path = path.replace('\\', '/');
if(!path.endsWith("/"))
{
path = path + "/";
}
//System.out.println("2:"+path+":"+getPWD());
}
catch(IOException ex)
{
Log.debug("Error: can not get pathname (local)!");
return false;
}
}
else
{
Log.debug("(local) No such path: \"" + p + "\"");
return false;
}
return true;
}
public String[] sortLs()
{
String dir = getPWD();
if(check(toNFS(dir)) == 3)
{
try
{
files = getExports();
}
catch(Exception ex)
{
Log.debug("Can not list exports:" + ex.toString());
ex.printStackTrace();
}
}
else
{
XFile f = new XFile(dir);
files = f.list();
}
if(files == null)
{
return new String[0];
}
size = new String[files.length];
perms = new int[files.length];
int accessible = 0;
for(int i = 0; i < files.length; i++)
{
XFile f2 = new XFile(dir + files[i]);
if(f2.isDirectory() && !files[i].endsWith("/"))
{
files[i] = files[i] + "/";
}
size[i] = "" + f2.length();
if(f2.canWrite())
{
accessible = FtpConnection.W;
}
else if(f2.canRead())
{
accessible = FtpConnection.R;
}
else
{
accessible = FtpConnection.DENIED;
}
perms[i] = accessible;
//System.out.println(pwd+files[i] +" : " +accessible + " : " + size[i]);
}
return files;
}
public String[] sortSize()
{
return size;
}
public int[] getPermissions()
{
return perms;
}
public int handleUpload(String f)
{
upload(f);
return 0;
}
public int handleDownload(String f)
{
download(f);
return 0;
}
public int upload(String f)
{
String file = toNFS(f);
if(file.endsWith("/"))
{
String out = StringUtils.getDir(file);
uploadDir(file, getLocalPath() + out);
fireActionFinished(this);
}
else
{
String outfile = StringUtils.getFile(file);
//System.out.println("transfer: " + file + ", " + getLocalPath() + outfile);
work(getLocalPath() + outfile, file);
fireActionFinished(this);
}
return 0;
}
public int download(String f)
{
String file = toNFS(f);
if(file.endsWith("/"))
{
String out = StringUtils.getDir(file);
downloadDir(file, getLocalPath() + out);
fireActionFinished(this);
}
else
{
String outfile = StringUtils.getFile(file);
//System.out.println("transfer: " + file + ", " + getLocalPath() + outfile);
work(file, getLocalPath() + outfile);
fireActionFinished(this);
}
return 0;
}
private void downloadDir(String dir, String out)
{
try
{
//System.out.println("downloadDir: " + dir + "," + out);
fileCount = 0;
shortProgress = true;
baseFile = StringUtils.getDir(dir);
XFile f2 = new XFile(dir);
String[] tmp = f2.list();
if(tmp == null)
{
return;
}
File fx = new File(out);
fx.mkdir();
for(int i = 0; i < tmp.length; i++)
{
tmp[i] = tmp[i].replace('\\', '/');
//System.out.println("1: " + dir+tmp[i] + ", " + out +tmp[i]);
XFile f3 = new XFile(dir + tmp[i]);
if(f3.isDirectory())
{
if(!tmp[i].endsWith("/"))
{
tmp[i] = tmp[i] + "/";
}
downloadDir(dir + tmp[i], out + tmp[i]);
}
else
{
fileCount++;
fireProgressUpdate(baseFile,
DataConnection.GETDIR + ":" + fileCount,
-1);
work(dir + tmp[i], out + tmp[i]);
}
}
fireProgressUpdate(baseFile,
DataConnection.DFINISHED + ":" + fileCount, -1);
}
catch(Exception ex)
{
ex.printStackTrace();
//System.out.println(dir + ", " + out);
Log.debug("Transfer error: " + ex);
fireProgressUpdate(baseFile,
DataConnection.FAILED + ":" + fileCount, -1);
}
shortProgress = false;
}
private void uploadDir(String dir, String out)
{
try
{
//System.out.println("uploadDir: " + dir + "," + out);
isDirUpload = true;
fileCount = 0;
shortProgress = true;
baseFile = StringUtils.getDir(dir);
File f2 = new File(out);
String[] tmp = f2.list();
if(tmp == null)
{
return;
}
XFile fx = new XFile(dir);
fx.mkdir();
for(int i = 0; i < tmp.length; i++)
{
tmp[i] = tmp[i].replace('\\', '/');
//System.out.println("1: " + dir+tmp[i] + ", " + out +tmp[i]);
File f3 = new File(out + tmp[i]);
if(f3.isDirectory())
{
if(!tmp[i].endsWith("/"))
{
tmp[i] = tmp[i] + "/";
}
uploadDir(dir + tmp[i], out + tmp[i]);
}
else
{
fileCount++;
fireProgressUpdate(baseFile,
DataConnection.PUTDIR + ":" + fileCount,
-1);
work(out + tmp[i], dir + tmp[i]);
}
}
fireProgressUpdate(baseFile,
DataConnection.DFINISHED + ":" + fileCount, -1);
}
catch(Exception ex)
{
ex.printStackTrace();
//System.out.println(dir + ", " + out);
Log.debug("Transfer error: " + ex);
fireProgressUpdate(baseFile,
DataConnection.FAILED + ":" + fileCount, -1);
}
isDirUpload = false;
shortProgress = true;
}
private void work(String file, String outfile)
{
BufferedOutputStream out = null;
BufferedInputStream in = null;
try
{
boolean outflag = false;
if(outfile.startsWith("nfs://"))
{
outflag = true;
out = new BufferedOutputStream(new XFileOutputStream(outfile));
}
else
{
out = new BufferedOutputStream(new FileOutputStream(outfile));
}
//System.out.println("out: " + outfile + ", in: " + file);
if(file.startsWith("nfs://"))
{
in = new BufferedInputStream(new XFileInputStream(file));
}
else
{
in = new BufferedInputStream(new FileInputStream(file));
}
byte[] buf = new byte[buffer];
int len = 0;
int reallen = 0;
//System.out.println(file+":"+getLocalPath()+outfile);
while(true)
{
len = in.read(buf);
//System.out.print(".");
if(len == StreamTokenizer.TT_EOF)
{
break;
}
out.write(buf, 0, len);
reallen += len;
//System.out.println(file + ":" + StringUtils.getFile(file));
if(outflag)
{
fireProgressUpdate(StringUtils.getFile(outfile),
DataConnection.PUT, reallen);
}
else
{
fireProgressUpdate(StringUtils.getFile(file),
DataConnection.GET, reallen);
}
}
fireProgressUpdate(file, DataConnection.FINISHED, -1);
}
catch(IOException ex)
{
Log.debug("Error with file IO (" + ex + ")!");
fireProgressUpdate(file, DataConnection.FAILED, -1);
}
finally
{
try
{
out.flush();
out.close();
in.close();
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
}
private void update(String file, String type, int bytes)
{
if(listeners == null)
{
return;
}
else
{
for(int i = 0; i < listeners.size(); i++)
{
ConnectionListener listener = (ConnectionListener) listeners.elementAt(i);
listener.updateProgress(file, type, bytes);
}
}
}
public void addConnectionListener(ConnectionListener l)
{
listeners.add(l);
}
public void setConnectionListeners(Vector l)
{
listeners = l;
}
/** remote directory has changed */
public void fireDirectoryUpdate()
{
if(listeners == null)
{
return;
}
else
{
for(int i = 0; i < listeners.size(); i++)
{
((ConnectionListener) listeners.elementAt(i)).updateRemoteDirectory(this);
}
}
}
/** progress update */
public void fireProgressUpdate(String file, String type, int bytes)
{
//System.out.println(listener);
if(listeners == null)
{
return;
}
else
{
for(int i = 0; i < listeners.size(); i++)
{
ConnectionListener listener = (ConnectionListener) listeners.elementAt(i);
if(shortProgress && Settings.shortProgress)
{
if(type.startsWith(DataConnection.DFINISHED))
{
listener.updateProgress(baseFile,
DataConnection.DFINISHED + ":" +
fileCount, bytes);
}
else if(isDirUpload)
{
listener.updateProgress(baseFile,
DataConnection.PUTDIR + ":" +
fileCount, bytes);
}
else
{
listener.updateProgress(baseFile,
DataConnection.GETDIR + ":" +
fileCount, bytes);
}
}
else
{
listener.updateProgress(file, type, bytes);
}
}
}
}
public void fireActionFinished(NfsConnection con)
{
if(listeners == null)
{
return;
}
else
{
for(int i = 0; i < listeners.size(); i++)
{
((ConnectionListener) listeners.elementAt(i)).actionFinished(con);
}
}
}
public int upload(String file, InputStream i)
{
BufferedInputStream in = null;
BufferedOutputStream out = null;
try
{
file = toNFS(file);
out = new BufferedOutputStream(new XFileOutputStream(file));
in = new BufferedInputStream(i);
byte[] buf = new byte[buffer];
int len = 0;
int reallen = 0;
while(true)
{
len = in.read(buf);
if(len == StreamTokenizer.TT_EOF)
{
break;
}
out.write(buf, 0, len);
reallen += len;
fireProgressUpdate(StringUtils.getFile(file),
DataConnection.PUT, reallen);
}
fireProgressUpdate(file, DataConnection.FINISHED, -1);
}
catch(IOException ex)
{
Log.debug("Error with file IO (" + ex + ")!");
fireProgressUpdate(file, DataConnection.FAILED, -1);
return -1;
}
finally
{
try
{
out.flush();
out.close();
in.close();
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
return 0;
}
public InputStream getDownloadInputStream(String file)
{
file = toNFS(file);
Log.debug(file);
try
{
return new BufferedInputStream(new XFileInputStream(file));
}
catch(Exception ex)
{
ex.printStackTrace();
Log.debug(ex.toString() +
" @NfsConnection::getDownloadInputStream");
return null;
}
}
public Date[] sortDates()
{
return null;
}
public boolean rename(String from, String to)
{
Log.debug("Not implemented!");
return false;
}
}