/*******************************************************************************
* Copyright (c) 2007, 2011 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Wind River Systems - initial API and implementation
* Martin Oberhuber (Wind River) - [238564] Adopt TM 3.0 APIs
* Uwe Stieber (Wind River) - [271224] NPE in TCFFileService#download
* Uwe Stieber (Wind River) - [271227] Fix compiler warnings in org.eclipse.tcf.rse
* Uwe Stieber (Wind River) - [274277] The TCF file service subsystem implementation is not updating the progress monitor
* Intel Corporation - [326489] Make recursive copy/delete available (delete/copy a folder contains files)
* Intel Corporation - [329654] Make all sub services operate against TCF connector service
*******************************************************************************/
package org.eclipse.tcf.internal.rse.files;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.rse.core.model.IHost;
import org.eclipse.rse.services.clientserver.FileTypeMatcher;
import org.eclipse.rse.services.clientserver.IMatcher;
import org.eclipse.rse.services.clientserver.NamePatternMatcher;
import org.eclipse.rse.services.clientserver.messages.SimpleSystemMessage;
import org.eclipse.rse.services.clientserver.messages.SystemMessage;
import org.eclipse.rse.services.clientserver.messages.SystemMessageException;
import org.eclipse.rse.services.clientserver.messages.SystemOperationFailedException;
import org.eclipse.rse.services.files.AbstractFileService;
import org.eclipse.rse.services.files.IHostFile;
import org.eclipse.tcf.internal.rse.Activator;
import org.eclipse.tcf.internal.rse.ITCFService;
import org.eclipse.tcf.internal.rse.Messages;
import org.eclipse.tcf.internal.rse.TCFConnectorService;
import org.eclipse.tcf.internal.rse.TCFConnectorServiceManager;
import org.eclipse.tcf.internal.rse.TCFRSETask;
import org.eclipse.tcf.protocol.IToken;
import org.eclipse.tcf.protocol.Protocol;
import org.eclipse.tcf.services.IFileSystem;
import org.eclipse.tcf.services.IFileSystem.DirEntry;
import org.eclipse.tcf.services.IFileSystem.FileAttrs;
import org.eclipse.tcf.services.IFileSystem.FileSystemException;
import org.eclipse.tcf.services.IFileSystem.IFileHandle;
import org.eclipse.tcf.util.TCFFileInputStream;
import org.eclipse.tcf.util.TCFFileOutputStream;
public class TCFFileService extends AbstractFileService {
private final TCFConnectorService connector;
private UserInfo user_info;
private static final class UserInfo {
final int r_uid;
final int e_uid;
final int r_gid;
final int e_gid;
final String home;
final Throwable error;
UserInfo(int r_uid, int e_uid, int r_gid, int e_gid, String home) {
this.r_uid = r_uid;
this.e_uid = e_uid;
this.r_gid = r_gid;
this.e_gid = e_gid;
this.home = home;
error = null;
}
UserInfo(Throwable error) {
this.error = error;
r_uid = -1;
e_uid = -1;
r_gid = -1;
e_gid = -1;
home = null;
}
}
public TCFFileService(IHost host) {
connector = (TCFConnectorService)TCFConnectorServiceManager
.getInstance().getConnectorService(host, ITCFService.class);
}
@Override
public String getDescription() {
return "The TCF File Service uses the Target Communication Framework to provide service" + //$NON-NLS-1$
"for the Files subsystem. It requires a TCF agent to be running on the remote machine."; //$NON-NLS-1$
}
public SystemMessage getMessage(Throwable x) {
return new SimpleSystemMessage(Activator.PLUGIN_ID,
SystemMessage.ERROR, x.getMessage(), x);
}
@Override
public String getName() {
return "TCF File Service"; //$NON-NLS-1$
}
private String toRemotePath(String parent, String name) throws SystemMessageException {
assert !Protocol.isDispatchThread();
String s = null;
if (parent != null) parent = parent.replace('\\', '/');
if (name != null) name = name.replace('\\', '/');
if (parent == null || parent.length() == 0) s = name;
else if (name == null || name.equals(".")) s = parent; //$NON-NLS-1$
else if (name.equals("/")) s = parent; //$NON-NLS-1$
else if (parent.endsWith("/")) s = parent + name; //$NON-NLS-1$
else s = parent + '/' + name;
if (s.startsWith("./") || s.equals(".")) { //$NON-NLS-1$ //$NON-NLS-2$
UserInfo ui = getUserInfo();
if (ui.error != null) throw new SystemMessageException(getMessage(ui.error));
s = ui.home.replace('\\', '/') + s.substring(1);
}
while (s.endsWith("/.")) s = s.substring(0, s.length() - 2); //$NON-NLS-1$
return s;
}
/* Delete from UI action will call deleteBatch interface, yet
* for copy from UI action, it will call copy! It's totally
* inconsistency! For solving the problem, we have to modify
* the copy itself and made it recursive. We can't modify it
* in the same way as delete does!
*
*/
public void internalCopy(String srcParent,
String srcName, String tgtParent, String tgtName, IProgressMonitor monitor)
throws SystemMessageException, InterruptedException {
//Note the dest directory or file exist surely since UI operations have
//done something, rename it to copy of XXX
if (monitor != null)
{
if (monitor.isCanceled())
{
throw new InterruptedException(Messages.TCFFileService_UserCancellation);
}
}
try
{
//firstly create the target directory!
this.createFolder(tgtParent, tgtName, monitor);
//then copy the next level directory!
final String new_srcpath = toRemotePath(srcParent, srcName);
final String new_tgtpath = toRemotePath(tgtParent, tgtName);
IHostFile[] arrFiles = internalFetch(new_srcpath, null,
FILE_TYPE_FILES_AND_FOLDERS, monitor);
if (arrFiles == null || arrFiles.length <=0 )
return;
else
{
for (int i = 0; i < arrFiles.length; i++)
{
String srcFile = toRemotePath(new_srcpath, arrFiles[i].getName());
String tgtFile = toRemotePath(new_tgtpath, arrFiles[i].getName());
if (arrFiles[i].isFile())
{
copy(srcFile, tgtFile, monitor);
}
else
{
//do recursive directory copy!
internalCopy(new_srcpath, arrFiles[i].getName(), new_tgtpath,
arrFiles[i].getName(), monitor);
}
}
}
}
catch (SystemMessageException e)
{
e.printStackTrace();
throw new SystemMessageException(e.getSystemMessage());
}
catch (InterruptedException e)
{
throw new InterruptedException(Messages.TCFFileService_UserCancellation1);
}
}
public void copy(String srcParent,
String srcName, String tgtParent, String tgtName, IProgressMonitor monitor)
throws SystemMessageException {
if (monitor != null)
monitor.beginTask(Messages.TCFFileService_CopyingFiles, 1);
try {
IHostFile curFile = getFile(srcParent, srcName, monitor);
final String srcFile = toRemotePath(srcParent, srcName);
final String tgtFile = toRemotePath(tgtParent, tgtName);
if (curFile.isFile())
copy(srcFile, tgtFile, monitor);
else if (curFile.isDirectory())
{
internalCopy(srcParent, srcName, tgtParent, tgtName, monitor);
}
else
{
FileNotFoundException e =
new FileNotFoundException(Messages.TCFFileService_FileNotFoundMessage);
throw new SystemMessageException(getMessage(e));
}
}
catch (Exception e) {
// TODO Auto-generated catch block
if (e instanceof SystemMessageException)
throw (SystemMessageException)e;
throw new SystemOperationFailedException(Activator.PLUGIN_ID, e);
}
finally {
if (monitor != null)
monitor.done();
}
}
public void copy(final String srcFile, final String tgtFile, IProgressMonitor monitor)
throws SystemMessageException {
new TCFRSETask<Boolean>() {
public void run() {
IFileSystem fs = connector.getFileSystemService();
fs.copy(srcFile, tgtFile, false, false, new IFileSystem.DoneCopy() {
public void doneCopy(IToken token, FileSystemException error) {
if (error != null) error(error);
else done(Boolean.TRUE);
}
});
}
}.getS(monitor, "Copy: " + srcFile); //$NON-NLS-1$
}
public void copyBatch(String[] srcParents,
String[] srcNames, String tgtParent, IProgressMonitor monitor) throws SystemMessageException {
for (int i = 0; i < srcParents.length; i++) {
copy(srcParents[i], srcNames[i], tgtParent, srcNames[i], monitor);
}
}
public IHostFile createFile(String parent,
String name, IProgressMonitor monitor) throws SystemMessageException {
try {
getOutputStream(parent, name, true, monitor).close();
return getFile(parent, name, monitor);
}
catch (IOException e) {
throw new SystemMessageException(getMessage(e));
}
}
public IHostFile createFolder(final String parent, final String name, IProgressMonitor monitor) throws SystemMessageException {
final String path = toRemotePath(parent, name);
return new TCFRSETask<IHostFile>() {
public void run() {
final IFileSystem fs = connector.getFileSystemService();
fs.mkdir(path, null, new IFileSystem.DoneMkDir() {
public void doneMkDir(IToken token, FileSystemException error) {
if (error != null) {
error(error);
return;
}
fs.stat(path, new IFileSystem.DoneStat() {
public void doneStat(IToken token,
FileSystemException error, FileAttrs attrs) {
if (error != null) error(error);
else done(new TCFFileResource(TCFFileService.this,
path, null, attrs, false));
}
});
}
});
}
}.getS(monitor, "Create folder"); //$NON-NLS-1$
}
public void delete(String parent,
String name, IProgressMonitor monitor) throws SystemMessageException {
final String path = toRemotePath(parent, name);
new TCFRSETask<Boolean>() {
public void run() {
final IFileSystem fs = connector.getFileSystemService();
fs.stat(path, new IFileSystem.DoneStat() {
public void doneStat(IToken token,
FileSystemException error, FileAttrs attrs) {
if (error != null) {
error(error);
return;
}
IFileSystem.DoneRemove done = new IFileSystem.DoneRemove() {
public void doneRemove(IToken token, FileSystemException error) {
if (error != null) {
error(error);
return;
}
done(Boolean.TRUE);
}
};
if (attrs.isDirectory()) {
fs.rmdir(path, done);
}
else {
fs.remove(path, done);
}
}
});
}
}.getS(monitor, "Delete"); //$NON-NLS-1$
}
private void internalDelete(String parent, String name,
IProgressMonitor monitor)
throws SystemMessageException, InterruptedException
{
if (monitor != null)
{
if (monitor.isCanceled())
{
throw new InterruptedException(Messages.TCFFileService_UserDeleteCancellation);
}
}
try
{
final String new_path = toRemotePath(parent, name);
IHostFile[] arrFiles = internalFetch(new_path, null,
FILE_TYPE_FILES_AND_FOLDERS, monitor);
if (arrFiles == null || arrFiles.length <= 0)
{
//This is an empty directory, directly delete!
delete(parent, name, monitor);
}
else
{
for (int i = 0; i < arrFiles.length; i++)
{
if (arrFiles[i].isFile())
{
delete(new_path, arrFiles[i].getName(), monitor);
}
else
internalDelete(new_path, arrFiles[i].getName(), monitor);
}
//now the folder becomes empty, let us delete it!
delete(parent, name, monitor);
}
}
catch (SystemMessageException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new SystemMessageException(e.getSystemMessage());
}
catch (InterruptedException e) {
throw new InterruptedException(Messages.TCFFileService_UserDeleteCancellation1);
}
}
@Override
public void deleteBatch(String[] remoteParents, String[] fileNames,
IProgressMonitor monitor)
throws SystemMessageException {
if (monitor != null)
monitor.beginTask(Messages.TCFFileService_DeletingFiles, remoteParents.length);
try
{
for (int i = 0; i < remoteParents.length; i++) {
IHostFile curFile = getFile(remoteParents[i], fileNames[i], monitor);
if (curFile.isFile())
delete(remoteParents[i], fileNames[i], monitor);
else if (curFile.isDirectory())
internalDelete(remoteParents[i], fileNames[i], monitor);
}
}
catch (Exception x) {
if (x instanceof SystemMessageException) throw (SystemMessageException)x;
throw new SystemOperationFailedException(Activator.PLUGIN_ID, x);
}
finally {
if (monitor != null)
monitor.done();
}
}
public void download(final String parent,
final String name, final File file, final boolean is_binary,
final String host_encoding, IProgressMonitor monitor) throws SystemMessageException {
IHostFile hostFile = getFile(parent, name, new NullProgressMonitor());
monitor.beginTask("Downloading " + toRemotePath(parent, name) + " ...", Long.valueOf(hostFile.getSize() / 1024).intValue()); //$NON-NLS-1$ //$NON-NLS-2$
try {
file.getParentFile().mkdirs();
InputStream inp = getInputStream(parent, name, is_binary, new NullProgressMonitor());
OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
copyStream(inp, out, is_binary, "UTF8", host_encoding, monitor); //$NON-NLS-1$
}
catch (Exception x) {
if (x instanceof SystemMessageException) throw (SystemMessageException)x;
throw new SystemOperationFailedException(Activator.PLUGIN_ID, x);
}
finally {
monitor.done();
}
}
@Override
public String getEncoding(IProgressMonitor monitor) throws SystemMessageException {
return "UTF8"; //$NON-NLS-1$
}
public IHostFile getFile(final String parent,
final String name, IProgressMonitor monitor) throws SystemMessageException {
final String path = toRemotePath(parent, name);
return new TCFRSETask<IHostFile>() {
public void run() {
IFileSystem fs = connector.getFileSystemService();
fs.stat(path, new IFileSystem.DoneStat() {
public void doneStat(IToken token,
FileSystemException error, FileAttrs attrs) {
if (error != null) {
if (error.getStatus() == IFileSystem.STATUS_NO_SUCH_FILE) {
done(new TCFFileResource(TCFFileService.this, path, null, null, false));
return;
}
error(error);
return;
}
done(new TCFFileResource(TCFFileService.this, path, null, attrs, false));
}
});
}
}.getS(monitor, "Stat"); //$NON-NLS-1$
}
@Override
protected IHostFile[] internalFetch(final String parent, final String filter, final int fileType, final IProgressMonitor monitor)
throws SystemMessageException {
final String path = toRemotePath(parent, null);
final boolean wantFiles = (fileType==FILE_TYPE_FILES_AND_FOLDERS || (fileType&FILE_TYPE_FILES)!=0);
final boolean wantFolders = (fileType==FILE_TYPE_FILES_AND_FOLDERS || (fileType%FILE_TYPE_FOLDERS)!=0);
return new TCFRSETask<IHostFile[]>() {
private IMatcher matcher = null;
public void run() {
if (filter == null) {
matcher = null;
}
else if (filter.endsWith(",")) { //$NON-NLS-1$
String[] types = filter.split(","); //$NON-NLS-1$
matcher = new FileTypeMatcher(types, true);
}
else {
matcher = new NamePatternMatcher(filter, true, true);
}
final List<TCFFileResource> results = new ArrayList<TCFFileResource>();
final IFileSystem fs = connector.getFileSystemService();
fs.opendir(path, new IFileSystem.DoneOpen() {
public void doneOpen(IToken token, FileSystemException error, final IFileHandle handle) {
if (error != null) {
error(error);
return;
}
fs.readdir(handle, new IFileSystem.DoneReadDir() {
public void doneReadDir(IToken token,
FileSystemException error, DirEntry[] entries, boolean eof) {
if (error != null) {
error(error);
return;
}
for (DirEntry e : entries) {
if (e.attrs == null) {
// Attrs are not available if, for example,
// the entry is a broken symbolic link
}
else if (e.attrs.isDirectory()) {
// dont filter folder names if getting both folders and files
if (wantFolders && (matcher==null || fileType==FILE_TYPE_FILES_AND_FOLDERS || matcher.matches(e.filename))) {
results.add(new TCFFileResource(TCFFileService.this,
path, e.filename, e.attrs, false));
}
}
else if (e.attrs.isFile()) {
if (wantFiles && (matcher == null || matcher.matches(e.filename))) {
results.add(new TCFFileResource(TCFFileService.this,
path, e.filename, e.attrs, false));
}
}
}
if (eof) {
fs.close(handle, new IFileSystem.DoneClose() {
public void doneClose(IToken token, FileSystemException error) {
if (error != null) {
error(error);
return;
}
done(results.toArray(new TCFFileResource[results.size()]));
}
});
}
else {
fs.readdir(handle, this);
}
}
});
}
});
}
}.getS(monitor, "Get files and folders"); //$NON-NLS-1$
}
@Override
public InputStream getInputStream(final String parent, final String name, boolean isBinary, IProgressMonitor monitor)
throws SystemMessageException {
final String path = toRemotePath(parent, name);
final IFileHandle handle = new TCFRSETask<IFileHandle>() {
public void run() {
IFileSystem fs = connector.getFileSystemService();
fs.open(path, IFileSystem.TCF_O_READ, null, new IFileSystem.DoneOpen() {
public void doneOpen(IToken token, FileSystemException error, IFileHandle handle) {
if (error != null) error(error);
else done(handle);
}
});
}
}.getS(monitor, "Get input stream"); //$NON-NLS-1$
return new TCFFileInputStream(handle);
}
@Override
public OutputStream getOutputStream(final String parent, final String name, boolean isBinary, IProgressMonitor monitor)
throws SystemMessageException {
final String path = toRemotePath(parent, name);
final IFileHandle handle = new TCFRSETask<IFileHandle>() {
public void run() {
IFileSystem fs = connector.getFileSystemService();
int flags = IFileSystem.TCF_O_WRITE | IFileSystem.TCF_O_CREAT | IFileSystem.TCF_O_TRUNC;
fs.open(path, flags, null, new IFileSystem.DoneOpen() {
public void doneOpen(IToken token, FileSystemException error, IFileHandle handle) {
if (error != null) error(error);
else done(handle);
}
});
}
}.getS(monitor, "Get output stream"); //$NON-NLS-1$
return new TCFFileOutputStream(handle);
}
public IHostFile[] getRoots(IProgressMonitor monitor) throws SystemMessageException {
return new TCFRSETask<IHostFile[]>() {
public void run() {
IFileSystem fs = connector.getFileSystemService();
fs.roots(new IFileSystem.DoneRoots() {
public void doneRoots(IToken token, FileSystemException error, DirEntry[] entries) {
if (error != null) {
error(error);
return;
}
List<TCFFileResource> l = new ArrayList<TCFFileResource>();
for (DirEntry e : entries) {
if (e.attrs == null) continue;
l.add(new TCFFileResource(TCFFileService.this, null, e.filename, e.attrs, true));
}
done(l.toArray(new IHostFile[l.size()]));
}
});
}
}.getS(monitor, "Get roots"); //$NON-NLS-1$
}
public IHostFile getUserHome() {
UserInfo ui = getUserInfo();
try {
return getFile(ui.home, ".", new NullProgressMonitor()); //$NON-NLS-1$
}
catch (SystemMessageException e) {
throw new Error(e);
}
}
public boolean isCaseSensitive() {
return true;
}
public void move(final String srcParent,
final String srcName, final String tgtParent, final String tgtName, IProgressMonitor monitor)
throws SystemMessageException {
final String src_path = toRemotePath(srcParent, srcName);
final String tgt_path = toRemotePath(tgtParent, tgtName);
new TCFRSETask<Boolean>() {
public void run() {
IFileSystem fs = connector.getFileSystemService();
fs.rename(src_path, tgt_path, new IFileSystem.DoneRename() {
public void doneRename(IToken token, FileSystemException error) {
if (error != null) error(error);
else done(Boolean.TRUE);
}
});
}
}.getS(monitor, "Move"); //$NON-NLS-1$
}
public void rename(String remoteParent,
String oldName, String newName, IProgressMonitor monitor) throws SystemMessageException {
move(remoteParent, oldName, remoteParent, newName, monitor);
}
public void rename(String remoteParent,
String oldName, String newName, IHostFile oldFile, IProgressMonitor monitor)
throws SystemMessageException {
move(remoteParent, oldName, remoteParent, newName, monitor);
oldFile.renameTo(toRemotePath(remoteParent, newName));
}
public void setLastModified(final String parent,
final String name, final long timestamp, IProgressMonitor monitor) throws SystemMessageException {
final String path = toRemotePath(parent, name);
new TCFRSETask<Boolean>() {
public void run() {
IFileSystem fs = connector.getFileSystemService();
FileAttrs attrs = new FileAttrs(IFileSystem.ATTR_ACMODTIME,
0, 0, 0, 0, timestamp, timestamp, null);
fs.setstat(path, attrs, new IFileSystem.DoneSetStat() {
public void doneSetStat(IToken token, FileSystemException error) {
if (error != null) error(error);
else done(Boolean.TRUE);
}
});
}
}.getS(monitor, "Set modification time"); //$NON-NLS-1$
}
public void setReadOnly(final String parent,
final String name, final boolean readOnly, IProgressMonitor monitor) throws SystemMessageException {
final String path = toRemotePath(parent, name);
new TCFRSETask<Boolean>() {
public void run() {
final IFileSystem fs = connector.getFileSystemService();
fs.stat(path, new IFileSystem.DoneStat() {
public void doneStat(IToken token, FileSystemException error, FileAttrs attrs) {
if (error != null) {
error(error);
return;
}
int p = attrs.permissions;
if (readOnly) {
p &= ~IFileSystem.S_IWUSR;
p &= ~IFileSystem.S_IWGRP;
p &= ~IFileSystem.S_IWOTH;
}
else {
p |= IFileSystem.S_IWUSR;
p |= IFileSystem.S_IWGRP;
p |= IFileSystem.S_IWOTH;
}
FileAttrs new_attrs = new FileAttrs(IFileSystem.ATTR_PERMISSIONS,
0, 0, 0, p, 0, 0, null);
fs.setstat(path, new_attrs, new IFileSystem.DoneSetStat() {
public void doneSetStat(IToken token, FileSystemException error) {
if (error != null) error(error);
else done(Boolean.TRUE);
}
});
}
});
}
}.getS(monitor, "Set permissions"); //$NON-NLS-1$
}
public void upload(InputStream inp,
String parent, String name, boolean isBinary,
String hostEncoding, IProgressMonitor monitor) throws SystemMessageException {
monitor.beginTask("Upload", 1); //$NON-NLS-1$
try {
OutputStream out = getOutputStream(parent, name, isBinary, new NullProgressMonitor());
// As we cannot determine the local file size, redirect the worked ticks to a NullProgressMonitor.
copyStream(inp, out, isBinary, hostEncoding, "UTF8", new NullProgressMonitor()); //$NON-NLS-1$
}
catch (Throwable x) {
if (x instanceof SystemMessageException) throw (SystemMessageException)x;
throw new SystemMessageException(getMessage(x));
}
finally {
monitor.done();
}
}
public void upload(File localFile,
String parent, String name, boolean isBinary,
String srcEncoding, String hostEncoding, IProgressMonitor monitor)
throws SystemMessageException {
monitor.beginTask("Uploading " + localFile.toString() + " ...", Long.valueOf(localFile.length() / 1024).intValue()); //$NON-NLS-1$ //$NON-NLS-2$
try {
OutputStream out = getOutputStream(parent, name, isBinary, new NullProgressMonitor());
InputStream inp = new BufferedInputStream(new FileInputStream(localFile));
copyStream(inp, out, isBinary, hostEncoding, "UTF8", monitor); //$NON-NLS-1$
}
catch (Throwable x) {
if (x instanceof SystemMessageException) throw (SystemMessageException)x;
throw new SystemMessageException(getMessage(x));
}
finally {
monitor.done();
}
}
private void copyStream(InputStream inp, OutputStream out,
boolean is_binary, String inp_encoding, String out_encoding, IProgressMonitor monitor) throws IOException {
try {
if (!is_binary) {
if (inp_encoding == null || inp_encoding.equals("UTF-8")) inp_encoding = "UTF8"; //$NON-NLS-1$ //$NON-NLS-2$
if (out_encoding == null || out_encoding.equals("UTF-8")) out_encoding = "UTF8"; //$NON-NLS-1$ //$NON-NLS-2$
}
if (is_binary || inp_encoding.equals(out_encoding)) {
byte[] buf = new byte[0x1000];
for (;;) {
int buf_len = inp.read(buf);
if (buf_len < 0) break;
out.write(buf, 0, buf_len);
if (monitor != null) monitor.worked(buf_len / 1024);
}
}
else {
Reader reader = new InputStreamReader(inp, inp_encoding);
Writer writer = new OutputStreamWriter(out, out_encoding);
char[] buf = new char[0x1000];
for (;;) {
int buf_len = reader.read(buf);
if (buf_len < 0) break;
writer.write(buf, 0, buf_len);
if (monitor != null) monitor.worked(buf_len / 1024);
}
writer.flush();
}
}
finally {
out.close();
inp.close();
}
}
private synchronized UserInfo getUserInfo() {
if (user_info == null || user_info.error != null) {
user_info = new TCFRSETask<UserInfo>() {
public void run() {
IFileSystem fs = connector.getFileSystemService();
fs.user(new IFileSystem.DoneUser() {
public void doneUser(IToken token, FileSystemException error, int real_uid,
int effective_uid, int real_gid, int effective_gid, String home) {
if (error != null) done(new UserInfo(error));
else done(new UserInfo(real_uid, effective_uid, real_gid, effective_gid, home));
}
});
}
}.getE();
}
return user_info;
}
public boolean canRead(FileAttrs attrs) {
if ((attrs.flags & IFileSystem.ATTR_PERMISSIONS) == 0) return false;
if ((attrs.flags & IFileSystem.ATTR_UIDGID) == 0) return false;
UserInfo ui = getUserInfo();
if (ui.error != null) return false;
if (ui.e_uid == attrs.uid) {
return (attrs.permissions & IFileSystem.S_IRUSR) != 0;
}
if (ui.e_gid == attrs.gid) {
return (attrs.permissions & IFileSystem.S_IRGRP) != 0;
}
return (attrs.permissions & IFileSystem.S_IROTH) != 0;
}
public boolean canWrite(FileAttrs attrs) {
if ((attrs.flags & IFileSystem.ATTR_PERMISSIONS) == 0) return false;
if ((attrs.flags & IFileSystem.ATTR_UIDGID) == 0) return false;
UserInfo ui = getUserInfo();
if (ui.error != null) return false;
if (ui.e_uid == attrs.uid) {
return (attrs.permissions & IFileSystem.S_IWUSR) != 0;
}
if (ui.e_gid == attrs.gid) {
return (attrs.permissions & IFileSystem.S_IWGRP) != 0;
}
return (attrs.permissions & IFileSystem.S_IWOTH) != 0;
}
}