Package org.jnode.protocol.nfs.nfs2

Source Code of org.jnode.protocol.nfs.nfs2.NFS2OutputStream

/*
* $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.protocol.nfs.nfs2;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import org.jnode.net.nfs.Protocol;
import org.jnode.net.nfs.nfs2.CreateFileResult;
import org.jnode.net.nfs.nfs2.FileAttribute;
import org.jnode.net.nfs.nfs2.LookupResult;
import org.jnode.net.nfs.nfs2.NFS2Client;
import org.jnode.net.nfs.nfs2.NFS2Exception;
import org.jnode.net.nfs.nfs2.Time;
import org.jnode.net.nfs.nfs2.mount.ExportEntry;
import org.jnode.net.nfs.nfs2.mount.Mount1Client;
import org.jnode.net.nfs.nfs2.mount.MountException;
import org.jnode.net.nfs.nfs2.mount.MountResult;

public class NFS2OutputStream extends OutputStream {
    private static final boolean DEFAULT_PERMISSION[] =
            new boolean[] {true, true, false, true, false, false, true, false, false};
    private static final int DEFAULT_BUFFER_SIZE = NFS2Client.MAX_DATA;
    private Mount1Client mountClient;
    private NFS2Client nfsClient;
    private String mountDirectory;
    private byte[] fileHandle;
    @SuppressWarnings("unused")
    private FileAttribute fileAttribute;
    private long fileOffset;
    private byte[] buffer;
    private int count;

    public NFS2OutputStream(URL url) throws IOException {
        int uid;
        int gid;
        String userinfo = url.getUserInfo();
        if (userinfo != null) {
            final int pos = userinfo.indexOf(':');
            if (pos != -1) {
                uid = Integer.parseInt(userinfo.substring(0, pos));
                gid = Integer.parseInt(userinfo.substring(pos + 1));
            } else {
                throw new IOException("The url doesn't contains the uid and guid.");
            }
        } else {
            throw new IOException("The url doesn't contains the uid and guid.");
        }

        mountClient = new Mount1Client(InetAddress.getByName(url.getHost()), Protocol.TCP, uid, gid);
        nfsClient = new NFS2Client(InetAddress.getByName(url.getHost()), Protocol.TCP, uid, gid);
        String path = url.getPath();
        List<ExportEntry> exportList;
        try {
            exportList = mountClient.export();
        } catch (MountException e1) {
            mountClient.close();
            throw new IOException(e1.getMessage());
        }

        ExportEntry exportEntry = null;
        for (ExportEntry e : exportList) {
            if (path.startsWith(e.getDirectory())) {
                if (exportEntry == null) {
                    exportEntry = e;
                } else {
                    if (exportEntry.getDirectory().length() < e.getDirectory().length()) {
                        exportEntry = e;
                    }
                }
            }
        }
        if (exportEntry == null) {
            throw new IOException("The path " + path + " it is not exported");
        }
        mountDirectory = exportEntry.getDirectory();
        MountResult mountResult;
        try {
            mountResult = mountClient.mount(mountDirectory);
        } catch (MountException e) {
            mountClient.close();
            throw new IOException(e.getMessage());
        }

        byte[] tempFileHandle = mountResult.getFileHandle();
        try {
            String filePath = path.substring(exportEntry.getDirectory().length());
            StringTokenizer tokenizer = new StringTokenizer(filePath, "/");
            List<String> tokenList = new ArrayList<String>();
            while (tokenizer.hasMoreElements()) {
                String t = tokenizer.nextToken();
                tokenList.add(t);
            }
            for (int i = 0; i < tokenList.size() - 1; i++) {
                String t = tokenList.get(i);
                LookupResult lookup = nfsClient.lookup(tempFileHandle, t);
                if (lookup.getFileAttribute().getType() == FileAttribute.FILE) {
                    throw new IOException("The path contains a file : " + t + '.');
                } else if (lookup.getFileAttribute().getType() == FileAttribute.DIRECTORY) {
                    tempFileHandle = lookup.getFileHandle();
                } else {
                    throw new IOException("The path contains an unknow resource: " + t +
                            ". It is not directory or file");
                }
            }
            CreateFileResult result =
                    nfsClient.createFile(tempFileHandle, tokenList.get(tokenList.size() - 1),
                            DEFAULT_PERMISSION, uid, gid, 0, new Time(-1, -1), new Time(-1, -1));
            fileHandle = result.getFileHandle();
            fileAttribute = result.getFileAttribute();
        } catch (NFS2Exception e) {
            try {
                mountClient.unmount(mountDirectory);
            } catch (MountException e1) {
                // ignore
            }
            mountClient.close();
            nfsClient.close();
            throw new IOException(e.getMessage());
        }
        if (fileHandle == null) {
            throw new IOException("The target of the " + url.toString() + " it is not a file.");
        }
        buffer = new byte[DEFAULT_BUFFER_SIZE];
    }

    private void flushBuffer() throws IOException {
        if (count == 0) {
            return;
        }
        try {
            fileAttribute = nfsClient.writeFile(fileHandle, (int) fileOffset, buffer, 0, count);
        } catch (NFS2Exception e) {
            throw new IOException(e);
        }
        fileOffset += count;
        count = 0;
    }

    @Override
    public synchronized void write(int b) throws IOException {
        if (count >= buffer.length) {
            flushBuffer();
        }
        buffer[count] = (byte) b;
        count++;
    }

    @Override
    public synchronized void flush() throws IOException {
        flushBuffer();
    }

    @Override
    public synchronized void write(byte[] b, int off, int len) throws IOException {
        int writeBytes = 0;
        while (writeBytes != len) {
            if (count >= buffer.length) {
                flushBuffer();
            }
            int c = Math.min(buffer.length - count, len - writeBytes);
            System.arraycopy(b, off + writeBytes, buffer, count, c);
            writeBytes += c;
            count += c;
        }
    }

    // TODO Remove the synch in the future
    @Override
    public synchronized void close() throws IOException {
        if (mountClient != null) {
            try {
                mountClient.unmount(mountDirectory);
            } catch (MountException e) {
                // ignore
            }
            try {
                mountClient.close();
            } catch (IOException e) {
                // ignore
            }
        }
        if (nfsClient != null) {
            try {
                nfsClient.close();
            } catch (IOException e) {
                // ignore
            }
        }
    }
}
TOP

Related Classes of org.jnode.protocol.nfs.nfs2.NFS2OutputStream

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.