Package org.jnode.net.nfs.nfs2

Source Code of org.jnode.net.nfs.nfs2.NFS2Client$ResultWithCode

/*
* $Id$
*
* Copyright (C) 2003-2014 JNode.org
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jnode.net.nfs.nfs2;

import java.io.IOException;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import org.acplt.oncrpc.OncRpcClient;
import org.acplt.oncrpc.OncRpcClientAuthUnix;
import org.acplt.oncrpc.OncRpcException;
import org.acplt.oncrpc.OncRpcPortmapClient;
import org.acplt.oncrpc.OncRpcProtocols;
import org.acplt.oncrpc.OncRpcTcpClient;
import org.acplt.oncrpc.OncRpcUdpClient;
import org.acplt.oncrpc.XdrAble;
import org.acplt.oncrpc.XdrDecodingStream;
import org.acplt.oncrpc.XdrEncodingStream;
import org.acplt.oncrpc.XdrVoid;
import org.apache.log4j.Logger;
import org.jnode.net.nfs.Protocol;

/**
* This class access a NFS2 server . It implements all the method from NFS2 specification
*  http://tools.ietf.org/html/rfc1094
*
* @author Andrei Dore
*/
public class NFS2Client {

    /**
     * The maximum number of bytes of data in a READ or WRITE request.
     */
    public static final int MAX_DATA = 8192;

    public static final int FILE_HANDLE_SIZE = 32;

    public static final int MAX_NAME_LENGTH = 255;

    public static final int MAX_PATH_LENGTH = 1024;

    public static final int COOKIE_SIZE = 4;

    /**
     * This constant it is use when we create a rpc client . The creation of the
     * rpc client need a buffer to store parameters or results . To create this
     * buffer we must know the max length of the buffer. The NFS2 specification
     * specify that for read write operation the maximun number of bytes it is
     * 8192.At this number we must add the length of the header(24), the lenght
     * of the auth part (400) and the length of the parameters in write
     * operation (16 +FILE_HANDLE_SIZE) . We chose to add the length of the
     * parameter in write operation because only in this case we risk a buffer
     * overflow.
     */
    private static final int HEADER_DATA = 440 + FILE_HANDLE_SIZE;

    private static final int NFS_VERSION = 2;

    private static final int NFS_PROGRAM = 100003;

    private static final int PROCEDURE_TEST = 0;

    private static final int PROCEDURE_GET_ATTRIBUTE = 1;

    private static final int PROCEDURE_SET_ATTRIBUTE = 2;

    private static final int PROCEDURE_LOOKUP = 4;

    private static final int PROCEDURE_READ_FILE = 6;

    private static final int PROCEDURE_WRITE_FILE = 8;

    private static final int PROCEDURE_CREATE_FILE = 9;

    private static final int PROCEDURE_REMOVE_FILE = 10;

    private static final int PROCEDURE_RENAME_FILE = 11;

    private static final int PROCEDURE_CREATE_DIRECTORY = 14;

    private static final int PROCEDURE_REMOVE_DIRECTORY = 15;

    private static final int PROCEDURE_LIST_DIRECTORY = 16;

    private static final int PROCEDURE_GET_FILE_SYSTEM_ATTRIBUTE = 17;

    private static final Logger LOGGER = Logger.getLogger(NFS2Client.class);

    private List<OncRpcClient> rpcClientPool;

    private InetAddress host;

    private Protocol protocol;

    private int uid;

    private int gid;

    private boolean closed;

    /**
     * Constructs a <code>NFS2Client</code> client stub proxy object from
     * which the NFS_PROGRAM remote program can be accessed.
     */
    public NFS2Client(InetAddress host, Protocol protocol, int uid, int gid) {
        this.host = host;
        this.protocol = protocol;
        this.uid = uid;
        this.gid = gid;
        rpcClientPool = new LinkedList<OncRpcClient>();
    }

    private OncRpcClient createRpcClient() throws OncRpcException, IOException {
        // invoke portmap
        OncRpcPortmapClient portmap = new OncRpcPortmapClient(host);
        int port;
        try {
            port = portmap.getPort(NFS_PROGRAM, NFS_VERSION,
                            protocol == Protocol.UDP ? OncRpcProtocols.ONCRPC_UDP
                                    : OncRpcProtocols.ONCRPC_TCP);
        } finally {
            portmap.close();
        }

        // create the client
        // We create the client with a buffer with lenght equals witn MAX_DATA +
        // 424 ( max header length)
        OncRpcClient client = null;
        if (protocol == Protocol.UDP) {
            client = new OncRpcUdpClient(host, NFS_PROGRAM, NFS_VERSION, port, MAX_DATA + HEADER_DATA);
        } else if (protocol == Protocol.TCP) {
            client = new OncRpcTcpClient(host, NFS_PROGRAM, NFS_VERSION, port, MAX_DATA + HEADER_DATA);
        } else {
            // TODO Do something
        }
        client.setTimeout(10000);
        if (uid != -1 && gid != -1) {
            client.setAuth(new OncRpcClientAuthUnix("test", uid, gid));
        }
        return client;
    }

    // TODO This lock it is not good because we wait an IO operation before we
    // free the lock . So the creation of the nfsclient must be outside of the
    // lock
    private synchronized OncRpcClient getRpcClient() throws OncRpcException, IOException {
        if (closed) {
            throw new IOException("The nfs client it is closed");
        }
        if (rpcClientPool.size() == 0) {
            // TODO Improve this lock
            return createRpcClient();
        } else {
            return rpcClientPool.remove(0);
        }
    }

    private synchronized void releaseRpcClient(OncRpcClient client) throws IOException {
        if (closed) {
            throw new IOException("The nfs client it is closed");
        }
        if (client != null) {
            rpcClientPool.add(client);
        }
    }

    private void call(final int functionId, final XdrAble parameter, final XdrAble result)
        throws NFS2Exception, IOException {
        OncRpcClient client = null;
        int countCall = 0;
        while (true) {
            try {
                countCall++;
                client = getRpcClient();
                if (result == XdrVoid.XDR_VOID) {
                    client.call(functionId, parameter, result);
                } else {
                    ResultWithCode nfsResult = new ResultWithCode(result);
                    client.call(functionId, parameter, nfsResult);
                    if (nfsResult.getResultCode() != ResultCode.NFS_OK) {
                        throw new NFS2Exception(nfsResult.getResultCode());
                    }
                }
                break;
            } catch (Exception e) {
                if (client != null) {
                    try {
                        client.close();
                    } catch (OncRpcException e1) {
                        // Ignore this
                    }
                    client = null;
                }
                if (e instanceof RuntimeException) {
                    throw (RuntimeException) e;
                }
                if (e instanceof OncRpcException) {
                    if (countCall > 5) {
                        throw new NFS2Exception(e.getMessage(), e);
                    } else {
                        LOGGER.warn("An error occurs when nfs file system try to call the rpc method. Reason: " +
                                        e.getMessage() + " . It will try again");
                        continue;
                    }
                } else {
                    throw new NFS2Exception(e.getMessage(), e);
                }
            } finally {

                if (client != null) {
                    try {
                        releaseRpcClient(client);
                    } catch (IOException e) {
                        // ignore
                    }
                }
            }
        }
    }

    public synchronized void close() throws IOException {
        closed = true;
        List<OncRpcException> exceptionList = new ArrayList<OncRpcException>();
        for (OncRpcClient client : rpcClientPool) {
            try {
                client.close();
            } catch (OncRpcException e) {
                exceptionList.add(e);
            }
        }
        if (exceptionList.size() != 0) {
            StringBuilder builder = new StringBuilder();
            builder.append("An error occurs when the mount client close connections. Reason:");
            for (OncRpcException anExceptionList : exceptionList) {
                builder.append(anExceptionList.getMessage());
                builder.append('.');
            }
            throw new IOException(builder.toString());
        }
    }

    /**
     * Call remote procedure test.
     *
     * @throws NFS2Exception
     * @throws IOException
     */
    public void test() throws NFS2Exception, IOException {
        call(PROCEDURE_TEST, XdrVoid.XDR_VOID, XdrVoid.XDR_VOID);
    }

    public LookupResult lookup(final byte[] fileHandle, final String entryName)
        throws NFS2Exception, IOException {
        XdrAble nfsParameter = new NFSParameter() {
            public void xdrEncode(XdrEncodingStream xdr) throws OncRpcException, IOException {
                xdr.xdrEncodeOpaque(fileHandle, NFS2Client.FILE_HANDLE_SIZE);
                xdr.xdrEncodeString(entryName);
            }
        };
        final LookupResult result = new LookupResult();
        XdrAble nfsResult = new NFSResult() {
            public void xdrDecode(XdrDecodingStream xdr) throws OncRpcException, IOException {
                result.setFileHandle(xdr.xdrDecodeOpaque(NFS2Client.FILE_HANDLE_SIZE));
                FileAttribute fileAttribute = new FileAttribute();
                xdrFileAttributeDecode(xdr, fileAttribute);
                result.setFileAttribute(fileAttribute);
            }
        };
        call(PROCEDURE_LOOKUP, nfsParameter, nfsResult);
        return result;
    }

    public ListDirectoryResult listDirectory(final byte[] fileHandle, final byte[] cookie,
            final int count) throws NFS2Exception, IOException {
        XdrAble nfsParameter = new NFSParameter() {
            public void xdrEncode(XdrEncodingStream xdr) throws OncRpcException, IOException {
                xdr.xdrEncodeOpaque(fileHandle, FILE_HANDLE_SIZE);
                xdr.xdrEncodeOpaque(cookie, COOKIE_SIZE);
                xdr.xdrEncodeInt(count);
            }
        };
        final ListDirectoryResult result = new ListDirectoryResult();
        XdrAble nfsResult = new NFSResult() {
            public void xdrDecode(XdrDecodingStream xdr) throws OncRpcException, IOException {
                List<Entry> entryList = new ArrayList<Entry>();
                while (xdr.xdrDecodeBoolean()) {
                    int fileId = xdr.xdrDecodeInt();
                    String name = xdr.xdrDecodeString();
                    byte[] cookie = xdr.xdrDecodeOpaque(COOKIE_SIZE);
                    Entry entry = new Entry(fileId, name, cookie);
                    entryList.add(entry);
                }
                result.setEntryList(entryList);
                result.setEof(xdr.xdrDecodeBoolean());
            }
        };
        call(PROCEDURE_LIST_DIRECTORY, nfsParameter, nfsResult);
        return result;
    }

    public ReadFileResult readFile(final byte[] fileHandle, final int offset, final int count)
        throws NFS2Exception, IOException {
        if (count > MAX_DATA) {
            throw new IllegalArgumentException(
                    "The number of bytes read by the nfs client can not be greater than " + MAX_DATA);
        }
        XdrAble nfsParameter = new NFSParameter() {
            public void xdrEncode(XdrEncodingStream xdr) throws OncRpcException, IOException {
                xdr.xdrEncodeOpaque(fileHandle, FILE_HANDLE_SIZE);
                xdr.xdrEncodeInt(offset);
                xdr.xdrEncodeInt(count);
                xdr.xdrEncodeInt(0);
            }
        };
        final ReadFileResult result = new ReadFileResult();
        XdrAble nfsResult = new NFSResult() {
            public void xdrDecode(XdrDecodingStream xdr) throws OncRpcException, IOException {
                FileAttribute fileAttribute = new FileAttribute();
                xdrFileAttributeDecode(xdr, fileAttribute);
                result.setFileAttribute(fileAttribute);
                // TODO Optimize this
                result.setData(xdr.xdrDecodeDynamicOpaque());
            }
        };
        call(PROCEDURE_READ_FILE, nfsParameter, nfsResult);
        return result;
    }

    public void removeDirectory(final byte[] fileHandle, final String name)
        throws NFS2Exception, IOException {
        NFSParameter nfsParameter = new NFSParameter() {
            public void xdrEncode(XdrEncodingStream xdr) throws OncRpcException, IOException {
                xdr.xdrEncodeOpaque(fileHandle, FILE_HANDLE_SIZE);
                xdr.xdrEncodeString(name);
            }
        };
        XdrAble nfsResult = new NFSResult() {
            public void xdrDecode(XdrDecodingStream xdr) throws OncRpcException, IOException {
            }
        };
        call(PROCEDURE_REMOVE_DIRECTORY, nfsParameter, nfsResult);
    }

    public void removeFile(final byte[] parentFileHandle, final String name)
        throws NFS2Exception, IOException {
        NFSParameter nfsParameter = new NFSParameter() {
            public void xdrEncode(XdrEncodingStream xdr) throws OncRpcException, IOException {
                xdr.xdrEncodeOpaque(parentFileHandle, FILE_HANDLE_SIZE);
                xdr.xdrEncodeString(name);
            }
        };
        XdrAble nfsResult = new NFSResult() {
            public void xdrDecode(XdrDecodingStream xdr) throws OncRpcException, IOException {
            }
        };
        call(PROCEDURE_REMOVE_FILE, nfsParameter, nfsResult);
    }

    public void renameFile(final byte[] fromParentFileHandle, final String fromName,
            final byte[] toParentFileHandle, final String toName) throws NFS2Exception, IOException {
        NFSParameter nfsParameter = new NFSParameter() {
            public void xdrEncode(XdrEncodingStream xdr) throws OncRpcException, IOException {
                xdr.xdrEncodeOpaque(fromParentFileHandle, FILE_HANDLE_SIZE);
                xdr.xdrEncodeString(fromName);
                xdr.xdrEncodeOpaque(toParentFileHandle, FILE_HANDLE_SIZE);
                xdr.xdrEncodeString(toName);
            }
        };

        XdrAble nfsResult = new NFSResult() {
            public void xdrDecode(XdrDecodingStream xdr) throws OncRpcException, IOException {
            }
        };
        call(PROCEDURE_RENAME_FILE, nfsParameter, nfsResult);
    }

    public CreateDirectoryResult createDirectory(final byte[] parentFileHandle, final String name,
            final boolean[] permission, final int uid, final int gid, final int size,
            final Time lastAccessed, final Time lastModified) throws NFS2Exception, IOException {
        if (name.length() > MAX_NAME_LENGTH) {
            throw new NFS2Exception("The name is too long.The maximun length is " + MAX_NAME_LENGTH);
        }

        final int mode = createMode(permission) | 0x4000;
        NFSParameter nfsParameter = new NFSParameter() {
            public void xdrEncode(XdrEncodingStream xdr) throws OncRpcException, IOException {
                xdr.xdrEncodeOpaque(parentFileHandle, FILE_HANDLE_SIZE);
                xdr.xdrEncodeString(name);
                xdr.xdrEncodeInt(mode);
                xdr.xdrEncodeInt(uid);
                xdr.xdrEncodeInt(gid);
                xdr.xdrEncodeInt(size);
                xdrEncodeTime(xdr, lastAccessed);
                xdrEncodeTime(xdr, lastModified);
            }
        };

        final CreateDirectoryResult result = new CreateDirectoryResult();
        XdrAble nfsResult = new NFSResult() {
            public void xdrDecode(XdrDecodingStream xdr) throws OncRpcException, IOException {
                result.setFileHandle(xdr.xdrDecodeOpaque(NFS2Client.FILE_HANDLE_SIZE));
                FileAttribute fileAttribute = new FileAttribute();
                xdrFileAttributeDecode(xdr, fileAttribute);
                result.setFileAttribute(fileAttribute);
            }
        };
        call(PROCEDURE_CREATE_DIRECTORY, nfsParameter, nfsResult);
        return result;
    }

    public CreateFileResult createFile(final byte[] parentFileHandle, final String name,
            final boolean[] permission, final int uid, final int gid, final int size,
            final Time lastAccessed, final Time lastModified) throws NFS2Exception, IOException {
        if (name.length() > MAX_NAME_LENGTH) {
            throw new NFS2Exception("The name is too long.The maximun length is " + MAX_NAME_LENGTH);
        }

        final int mode = createMode(permission) | 0x8000;
        NFSParameter nfsParameter = new NFSParameter() {
            public void xdrEncode(XdrEncodingStream xdr) throws OncRpcException, IOException {
                xdr.xdrEncodeOpaque(parentFileHandle, FILE_HANDLE_SIZE);
                xdr.xdrEncodeString(name);
                xdr.xdrEncodeInt(mode);
                xdr.xdrEncodeInt(uid);
                xdr.xdrEncodeInt(gid);
                xdr.xdrEncodeInt(size);
                xdrEncodeTime(xdr, lastAccessed);
                xdrEncodeTime(xdr, lastModified);
            }
        };

        final CreateFileResult result = new CreateFileResult();
        XdrAble nfsResult = new NFSResult() {
            public void xdrDecode(XdrDecodingStream xdr) throws OncRpcException, IOException {
                result.setFileHandle(xdr.xdrDecodeOpaque(NFS2Client.FILE_HANDLE_SIZE));
                FileAttribute fileAttribute = new FileAttribute();
                xdrFileAttributeDecode(xdr, fileAttribute);
                result.setFileAttribute(fileAttribute);
            }
        };
        call(PROCEDURE_CREATE_FILE, nfsParameter, nfsResult);
        return result;
    }

    public FileAttribute writeFile(final byte[] fileHandle, final int offset, final byte[] buffer)
        throws NFS2Exception, IOException {
        return writeFile(fileHandle, offset, buffer, 0, buffer.length);
    }

    public FileAttribute writeFile(final byte[] fileHandle, final int offset, final byte[] buffer,
            final int bufferIndex, final int bufferCount) throws NFS2Exception, IOException {
        NFSParameter nfsParameter = new NFSParameter() {
            public void xdrEncode(XdrEncodingStream xdr) throws OncRpcException, IOException {
                xdr.xdrEncodeOpaque(fileHandle, FILE_HANDLE_SIZE);
                xdr.xdrEncodeInt(0);
                xdr.xdrEncodeInt(offset);
                xdr.xdrEncodeInt(0);

                // encode an array of bytes
                xdr.xdrEncodeInt(bufferCount);
                xdr.xdrEncodeOpaque(buffer, bufferIndex, bufferCount);
            }
        };

        final FileAttribute fileAttribute = new FileAttribute();
        XdrAble nfsResult = new NFSResult() {
            public void xdrDecode(XdrDecodingStream xdr) throws OncRpcException, IOException {
                xdrFileAttributeDecode(xdr, fileAttribute);
            }
        };
        call(PROCEDURE_WRITE_FILE, nfsParameter, nfsResult);
        return fileAttribute;
    }

    public FileAttribute getAttribute(final byte[] fileHandle) throws NFS2Exception, IOException {
        XdrAble nfsParameter = new NFSParameter() {
            public void xdrEncode(XdrEncodingStream xdr) throws OncRpcException, IOException {
                xdr.xdrEncodeOpaque(fileHandle, FILE_HANDLE_SIZE);
            }
        };

        final FileAttribute fileAttribute = new FileAttribute();
        XdrAble nfsResult = new NFSResult() {
            public void xdrDecode(XdrDecodingStream xdr) throws OncRpcException, IOException {
                xdrFileAttributeDecode(xdr, fileAttribute);
            }
        };
        call(PROCEDURE_GET_ATTRIBUTE, nfsParameter, nfsResult);
        return fileAttribute;
    }

    /**
     * Set the attributes for file.
     *
     * @param fileHandle file handle.
     * @param mode mode.
     * @param uid
     * @param gid
     * @param size
     * @param lastAccessed
     * @param lastModified
     * @return the FileAttribute set
     * @throws NFS2Exception
     * @throws IOException
     */
    public FileAttribute setAttribute(final byte[] fileHandle, final int mode, final int uid,
            final int gid, final int size, final Time lastAccessed, final Time lastModified)
        throws NFS2Exception, IOException {
        XdrAble nfsParameter = new NFSParameter() {
            public void xdrEncode(XdrEncodingStream xdr) throws OncRpcException, IOException {
                xdr.xdrEncodeOpaque(fileHandle, FILE_HANDLE_SIZE);
                xdr.xdrEncodeInt(mode);
                xdr.xdrEncodeInt(uid);
                xdr.xdrEncodeInt(gid);
                xdr.xdrEncodeInt(size);
                xdrEncodeTime(xdr, lastAccessed);
                xdrEncodeTime(xdr, lastModified);
            }
        };

        final FileAttribute fileAttribute = new FileAttribute();
        XdrAble nfsResult = new NFSResult() {
            public void xdrDecode(XdrDecodingStream xdr) throws OncRpcException, IOException {
                xdrFileAttributeDecode(xdr, fileAttribute);
            }
        };
        call(PROCEDURE_SET_ATTRIBUTE, nfsParameter, nfsResult);
        return fileAttribute;
    }

    public FileSystemAttribute getFileSystemAttribute(final byte[] fileHandle)
        throws NFS2Exception, IOException {

        XdrAble nfsParameter = new NFSParameter() {
            public void xdrEncode(XdrEncodingStream xdr) throws OncRpcException, IOException {
                xdr.xdrEncodeOpaque(fileHandle, FILE_HANDLE_SIZE);
            }
        };

        final FileSystemAttribute fileSystemAttribute = new FileSystemAttribute();
        XdrAble nfsResult = new NFSResult() {
            public void xdrDecode(XdrDecodingStream xdr) throws OncRpcException, IOException {
                fileSystemAttribute.setTransferSize(xdrDecodeUnsignedInt(xdr));
                fileSystemAttribute.setBlockSize(xdrDecodeUnsignedInt(xdr));
                fileSystemAttribute.setBlockCount(xdrDecodeUnsignedInt(xdr));
                fileSystemAttribute.setFreeBlockCount(xdrDecodeUnsignedInt(xdr));
                fileSystemAttribute.setAvailableBlockCount(xdrDecodeUnsignedInt(xdr));
            }
        };
        call(PROCEDURE_GET_FILE_SYSTEM_ATTRIBUTE, nfsParameter, nfsResult);
        return fileSystemAttribute;
    }

    private int createMode(boolean[] data) {
        int mode = 0;

        // owner
        if (data[0]) {
            mode |= 0x100;
        }
        if (data[1]) {
            mode |= 0x80;
        }
        if (data[2]) {
            mode |= 0x40;
        }

        // group
        if (data[3]) {
            mode |= 0x20;
        }
        if (data[4]) {
            mode |= 0x10;
        }
        if (data[5]) {
            mode |= 0x8;
        }

        // other
        if (data[6]) {
            mode |= 0x4;
        }
        if (data[7]) {
            mode |= 0x2;
        }
        if (data[8]) {
            mode |= 0x1;
        }
        return mode;
    }

    private void xdrEncodeTime(XdrEncodingStream xdrEncodingStream, Time time)
        throws OncRpcException, IOException {
        xdrEncodingStream.xdrEncodeInt(time.getSeconds());
        xdrEncodingStream.xdrEncodeInt(time.getMicroSeconds());
    }

    private void xdrDecodeTime(XdrDecodingStream xdrDecodingStream, Time time)
        throws OncRpcException, IOException {
        time.setSeconds(xdrDecodingStream.xdrDecodeInt());
        time.setMicroSeconds(xdrDecodingStream.xdrDecodeInt());
    }

    private void xdrFileAttributeDecode(XdrDecodingStream xdr, FileAttribute fileAttribute)
        throws OncRpcException, IOException {
        fileAttribute.setType(xdr.xdrDecodeInt());
        fileAttribute.setMode(xdr.xdrDecodeInt());
        fileAttribute.setNlink(xdr.xdrDecodeInt());
        fileAttribute.setUid(xdr.xdrDecodeInt());
        fileAttribute.setGid(xdr.xdrDecodeInt());
        fileAttribute.setSize(xdr.xdrDecodeInt());
        fileAttribute.setBlocksize(xdr.xdrDecodeInt());
        fileAttribute.setRdev(xdr.xdrDecodeInt());
        fileAttribute.setBlocks(xdr.xdrDecodeInt());
        fileAttribute.setFsid(xdr.xdrDecodeInt());
        fileAttribute.setFileId(xdr.xdrDecodeInt());
        Time lastAccessedTime = new Time();
        xdrDecodeTime(xdr, lastAccessedTime);
        fileAttribute.setLastAccessed(lastAccessedTime);
        Time lastModifiedTime = new Time();
        xdrDecodeTime(xdr, lastModifiedTime);
        fileAttribute.setLastModified(lastModifiedTime);
        Time lastStatusChangedTime = new Time();
        xdrDecodeTime(xdr, lastStatusChangedTime);
        fileAttribute.setLastStatusChanged(lastStatusChangedTime);
    }

    private long xdrDecodeUnsignedInt(XdrDecodingStream xdr) throws OncRpcException, IOException {
        byte[] buffer = new byte[4];
        xdr.xdrDecodeOpaque(buffer);
        return ((buffer[0] & 0xFF) << 24 | (buffer[1] & 0xFF) << 16 |
                (buffer[2] & 0xFF) << 8 | (buffer[3] & 0xFF));
    }

    private abstract class NFSParameter implements XdrAble {
        public void xdrDecode(XdrDecodingStream arg0) throws OncRpcException, IOException {
        }
    }

    private abstract class NFSResult implements XdrAble {
        public void xdrEncode(XdrEncodingStream arg0) throws OncRpcException, IOException {
        }
    }

    private class ResultWithCode implements XdrAble {

        private ResultCode resultCode;

        private XdrAble xdrAble;

        public ResultWithCode(XdrAble xdrAble) {
            this.xdrAble = xdrAble;
        }

        public void xdrEncode(XdrEncodingStream xdr) throws OncRpcException, IOException {
        }

        public void xdrDecode(XdrDecodingStream xdr) throws OncRpcException, IOException {
            resultCode = ResultCode.getResultCode(xdr.xdrDecodeInt());
            if (resultCode == ResultCode.NFS_OK) {
                xdrAble.xdrDecode(xdr);
            }
        }

        public ResultCode getResultCode() {
            return resultCode;
        }
    }
}
TOP

Related Classes of org.jnode.net.nfs.nfs2.NFS2Client$ResultWithCode

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.