/*******************************************************************************
* Copyright (c) 2007, 2012 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
*******************************************************************************/
package org.eclipse.tcf.internal.services.remote;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.tcf.core.Command;
import org.eclipse.tcf.protocol.IChannel;
import org.eclipse.tcf.protocol.IErrorReport;
import org.eclipse.tcf.protocol.IToken;
import org.eclipse.tcf.protocol.JSON;
import org.eclipse.tcf.services.IFileSystem;
public class FileSystemProxy implements IFileSystem {
private final class FileHandle implements IFileHandle {
final String id;
FileHandle(String id) {
this.id = id;
}
public IFileSystem getService() {
return FileSystemProxy.this;
}
public String toString() {
return "[File Handle '" + id + "']";
}
}
private static final class Status extends FileSystemException implements IErrorReport {
private static final long serialVersionUID = -1636567076145085980L;
private final int status;
private final Map<String,Object> attrs;
Status(int status, String message, Map<String,Object> attrs) {
super(message);
this.status = status;
this.attrs = attrs;
}
Status(Exception x) {
super(x);
this.status = IErrorReport.TCF_ERROR_OTHER;
this.attrs = new HashMap<String,Object>();
}
public int getStatus() {
return status;
}
public int getErrorCode() {
Number n = (Number)attrs.get(ERROR_CODE);
if (n == null) return 0;
return n.intValue();
}
public int getAltCode() {
Number n = (Number)attrs.get(ERROR_ALT_CODE);
if (n == null) return 0;
return n.intValue();
}
public String getAltOrg() {
return (String)attrs.get(ERROR_ALT_ORG);
}
public Map<String, Object> getAttributes() {
return attrs;
}
}
private abstract class FileSystemCommand extends Command {
FileSystemCommand(String command, Object[] args) {
super(channel, FileSystemProxy.this, command, args);
}
@SuppressWarnings("unchecked")
public Status toFSError(Object data) {
if (data == null) return null;
Map<String,Object> map = (Map<String,Object>)data;
Number error_code = (Number)map.get(IErrorReport.ERROR_CODE);
Status s = new Status(error_code.intValue(),
"TCF command exception:" +
"\nCommand: " + getCommandString(0) +
"\nException: " + toErrorString(data) +
"\nError code: " + error_code, map);
Object caused_by = map.get(IErrorReport.ERROR_CAUSED_BY);
if (caused_by != null) s.initCause(toError(caused_by, false));
return s;
}
}
private final IChannel channel;
public FileSystemProxy(IChannel channel) {
this.channel = channel;
}
public IToken close(IFileHandle handle, final DoneClose done) {
assert handle.getService() == this;
String id = ((FileHandle)handle).id;
return new FileSystemCommand("close", new Object[]{ id }) {
public void done(Exception error, Object[] args) {
Status s = null;
if (error != null) {
s = new Status(error);
}
else {
assert args.length == 1;
s = toFSError(args[0]);
}
done.doneClose(token, s);
}
}.token;
}
public IToken setstat(String path, FileAttrs attrs, final DoneSetStat done) {
Object dt = toObject(attrs);
return new FileSystemCommand("setstat", new Object[]{ path, dt }) {
public void done(Exception error, Object[] args) {
Status s = null;
if (error != null) {
s = new Status(error);
}
else {
assert args.length == 1;
s = toFSError(args[0]);
}
done.doneSetStat(token, s);
}
}.token;
}
public IToken fsetstat(IFileHandle handle, FileAttrs attrs, final DoneSetStat done) {
assert handle.getService() == this;
String id = ((FileHandle)handle).id;
Object dt = toObject(attrs);
return new FileSystemCommand("fsetstat", new Object[]{ id, dt }) {
public void done(Exception error, Object[] args) {
Status s = null;
if (error != null) {
s = new Status(error);
}
else {
assert args.length == 1;
s = toFSError(args[0]);
}
done.doneSetStat(token, s);
}
}.token;
}
public IToken stat(String path, final DoneStat done) {
return new FileSystemCommand("stat", new Object[]{ path }) {
public void done(Exception error, Object[] args) {
Status s = null;
FileAttrs a = null;
if (error != null) {
s = new Status(error);
}
else {
assert args.length == 2;
s = toFSError(args[0]);
if (s == null) a = toFileAttrs(args[1]);
}
done.doneStat(token, s, a);
}
}.token;
}
public IToken fstat(IFileHandle handle, final DoneStat done) {
assert handle.getService() == this;
String id = ((FileHandle)handle).id;
return new FileSystemCommand("fstat", new Object[]{ id }) {
public void done(Exception error, Object[] args) {
Status s = null;
FileAttrs a = null;
if (error != null) {
s = new Status(error);
}
else {
assert args.length == 2;
s = toFSError(args[0]);
if (s == null) a = toFileAttrs(args[1]);
}
done.doneStat(token, s, a);
}
}.token;
}
public IToken lstat(String path, final DoneStat done) {
return new FileSystemCommand("lstat", new Object[]{ path }) {
public void done(Exception error, Object[] args) {
Status s = null;
FileAttrs a = null;
if (error != null) {
s = new Status(error);
}
else {
assert args.length == 2;
s = toFSError(args[0]);
if (s == null) a = toFileAttrs(args[1]);
}
done.doneStat(token, s, a);
}
}.token;
}
public IToken mkdir(String path, FileAttrs attrs, final DoneMkDir done) {
Object dt = toObject(attrs);
return new FileSystemCommand("mkdir", new Object[]{ path, dt }) {
public void done(Exception error, Object[] args) {
Status s = null;
if (error != null) {
s = new Status(error);
}
else {
assert args.length == 1;
s = toFSError(args[0]);
}
done.doneMkDir(token, s);
}
}.token;
}
public IToken open(String file_name, int flags, FileAttrs attrs, final DoneOpen done) {
Object dt = toObject(attrs);
return new FileSystemCommand("open", new Object[]{ file_name, Integer.valueOf(flags), dt }) {
public void done(Exception error, Object[] args) {
Status s = null;
FileHandle h = null;
if (error != null) {
s = new Status(error);
}
else {
assert args.length == 2;
s = toFSError(args[0]);
if (s == null) h = toFileHandle(args[1]);
}
done.doneOpen(token, s, h);
}
}.token;
}
public IToken opendir(String path, final DoneOpen done) {
return new FileSystemCommand("opendir", new Object[]{ path }) {
public void done(Exception error, Object[] args) {
Status s = null;
FileHandle h = null;
if (error != null) {
s = new Status(error);
}
else {
assert args.length == 2;
s = toFSError(args[0]);
if (s == null) h = toFileHandle(args[1]);
}
done.doneOpen(token, s, h);
}
}.token;
}
public IToken read(IFileHandle handle, long offset, int len, final DoneRead done) {
assert handle.getService() == this;
String id = ((FileHandle)handle).id;
return new FileSystemCommand("read", new Object[]{
id, Long.valueOf(offset), Integer.valueOf(len) }) {
public void done(Exception error, Object[] args) {
Status s = null;
byte[] b = null;
boolean eof = false;
if (error != null) {
s = new Status(error);
}
else {
assert args.length == 3;
s = toFSError(args[1]);
if (s == null) {
b = JSON.toByteArray(args[0]);
eof = ((Boolean)args[2]).booleanValue();
}
}
done.doneRead(token, s, b, eof);
}
}.token;
}
public IToken readdir(IFileHandle handle, final DoneReadDir done) {
assert handle.getService() == this;
String id = ((FileHandle)handle).id;
return new FileSystemCommand("readdir", new Object[]{ id }) {
public void done(Exception error, Object[] args) {
Status s = null;
DirEntry[] b = null;
boolean eof = false;
if (error != null) {
s = new Status(error);
}
else {
assert args.length == 3;
s = toFSError(args[1]);
if (s == null) {
b = toDirEntryArray(args[0]);
eof = ((Boolean)args[2]).booleanValue();
}
}
done.doneReadDir(token, s, b, eof);
}
}.token;
}
public IToken roots(final DoneRoots done) {
return new FileSystemCommand("roots", null) {
public void done(Exception error, Object[] args) {
Status s = null;
DirEntry[] b = null;
if (error != null) {
s = new Status(error);
}
else {
assert args.length == 2;
s = toFSError(args[1]);
if (s == null) b = toDirEntryArray(args[0]);
}
done.doneRoots(token, s, b);
}
}.token;
}
public IToken readlink(String path, final DoneReadLink done) {
return new FileSystemCommand("readlink", new Object[]{ path }) {
public void done(Exception error, Object[] args) {
Status s = null;
String p = null;
if (error != null) {
s = new Status(error);
}
else {
assert args.length == 2;
s = toFSError(args[0]);
if (s == null) p = (String)args[1];
}
done.doneReadLink(token, s, p);
}
}.token;
}
public IToken realpath(String path, final DoneRealPath done) {
return new FileSystemCommand("realpath", new Object[]{ path }) {
public void done(Exception error, Object[] args) {
Status s = null;
String p = null;
if (error != null) {
s = new Status(error);
}
else {
assert args.length == 2;
s = toFSError(args[0]);
if (s == null) p = (String)args[1];
}
done.doneRealPath(token, s, p);
}
}.token;
}
public IToken remove(String file_name, final DoneRemove done) {
return new FileSystemCommand("remove", new Object[]{ file_name }) {
public void done(Exception error, Object[] args) {
Status s = null;
if (error != null) {
s = new Status(error);
}
else {
assert args.length == 1;
s = toFSError(args[0]);
}
done.doneRemove(token, s);
}
}.token;
}
public IToken rename(String old_path, String new_path, final DoneRename done) {
return new FileSystemCommand("rename", new Object[]{ old_path, new_path }) {
public void done(Exception error, Object[] args) {
Status s = null;
if (error != null) {
s = new Status(error);
}
else {
assert args.length == 1;
s = toFSError(args[0]);
}
done.doneRename(token, s);
}
}.token;
}
public IToken rmdir(String path, final DoneRemove done) {
return new FileSystemCommand("rmdir", new Object[]{ path }) {
public void done(Exception error, Object[] args) {
Status s = null;
if (error != null) {
s = new Status(error);
}
else {
assert args.length == 1;
s = toFSError(args[0]);
}
done.doneRemove(token, s);
}
}.token;
}
public IToken symlink(String link_path, String target_path, final DoneSymLink done) {
return new FileSystemCommand("symlink", new Object[]{ link_path, target_path }) {
public void done(Exception error, Object[] args) {
Status s = null;
if (error != null) {
s = new Status(error);
}
else {
assert args.length == 1;
s = toFSError(args[0]);
}
done.doneSymLink(token, s);
}
}.token;
}
public IToken write(IFileHandle handle, long offset, byte[] data,
int data_pos, int data_size, final DoneWrite done) {
assert handle.getService() == this;
String id = ((FileHandle)handle).id;
return new FileSystemCommand("write", new Object[]{
id, Long.valueOf(offset), new JSON.Binary(data, data_pos, data_size) }) {
public void done(Exception error, Object[] args) {
Status s = null;
if (error != null) {
s = new Status(error);
}
else {
assert args.length == 1;
s = toFSError(args[0]);
}
done.doneWrite(token, s);
}
}.token;
}
public IToken copy(String src_path, String dst_path,
boolean copy_permissions, boolean copy_uidgid, final DoneCopy done) {
return new FileSystemCommand("copy", new Object[]{
src_path, dst_path, Boolean.valueOf(copy_permissions),
Boolean.valueOf(copy_uidgid) }) {
public void done(Exception error, Object[] args) {
Status s = null;
if (error != null) {
s = new Status(error);
}
else {
assert args.length == 1;
s = toFSError(args[0]);
}
done.doneCopy(token, s);
}
}.token;
}
public IToken user(final DoneUser done) {
return new FileSystemCommand("user", null) {
@Override
public void done(Exception error, Object[] args) {
Status s = null;
int r_uid = 0;
int e_uid = 0;
int r_gid = 0;
int e_gid = 0;
String home = null;
if (error != null) {
s = new Status(error);
}
else {
assert args.length == 5;
r_uid = ((Number)args[0]).intValue();
e_uid = ((Number)args[1]).intValue();
r_gid = ((Number)args[2]).intValue();
e_gid = ((Number)args[3]).intValue();
home = (String)args[4];
}
done.doneUser(token, s, r_uid, e_uid, r_gid, e_gid, home);
}
}.token;
}
public String getName() {
return NAME;
}
private Object toObject(FileAttrs attrs) {
if (attrs == null) return null;
Map<String,Object> m = new HashMap<String,Object>();
if (attrs.attributes != null) m.putAll(attrs.attributes);
if ((attrs.flags & ATTR_SIZE) != 0) {
m.put("Size", Long.valueOf(attrs.size));
}
if ((attrs.flags & ATTR_UIDGID) != 0) {
m.put("UID", Integer.valueOf(attrs.uid));
m.put("GID", Integer.valueOf(attrs.gid));
}
if ((attrs.flags & ATTR_PERMISSIONS) != 0) {
m.put("Permissions", Integer.valueOf(attrs.permissions));
}
if ((attrs.flags & ATTR_ACMODTIME) != 0) {
m.put("ATime", Long.valueOf(attrs.atime));
m.put("MTime", Long.valueOf(attrs.mtime));
}
return m;
}
@SuppressWarnings("unchecked")
private FileAttrs toFileAttrs(Object o) {
if (o == null) return null;
Map<String,Object> m = new HashMap<String,Object>((Map<String,Object>)o);
int flags = 0;
long size = 0;
int uid = 0;
int gid = 0;
int permissions = 0;
long atime = 0;
long mtime = 0;
Number n = (Number)m.remove("Size");
if (n != null) {
size = n.longValue();
flags |= ATTR_SIZE;
}
Number n1 = (Number)m.remove("UID");
Number n2 = (Number)m.remove("GID");
if (n1 != null && n2 != null) {
uid = n1.intValue();
gid = n2.intValue();
flags |= ATTR_UIDGID;
}
n = (Number)m.remove("Permissions");
if (n != null) {
permissions = n.intValue();
flags |= ATTR_PERMISSIONS;
}
n1 = (Number)m.remove("ATime");
n2 = (Number)m.remove("MTime");
if (n1 != null && n2 != null) {
atime = n1.longValue();
mtime = n2.longValue();
flags |= ATTR_ACMODTIME;
}
return new FileAttrs(flags, size, uid, gid, permissions, atime, mtime, m);
}
private FileHandle toFileHandle(Object o) {
if (o == null) return null;
return new FileHandle(o.toString());
}
@SuppressWarnings("unchecked")
private DirEntry[] toDirEntryArray(Object o) {
if (o == null) return null;
Collection<Map<String,Object>> c = (Collection<Map<String,Object>>)o;
DirEntry[] res = new DirEntry[c.size()];
int i = 0;
for (Map<String,Object> m : c) {
res[i++] = new DirEntry(
(String)m.get("FileName"),
(String)m.get("LongName"),
toFileAttrs(m.get("Attrs")));
}
return res;
}
}