Package xbird.util.xfer

Source Code of xbird.util.xfer.TransferUtils

/*
* @(#)$Id$
*
* Copyright 2006-2008 Makoto YUI
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Contributors:
*     Makoto YUI - initial implementation
*/
package xbird.util.xfer;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.nio.channels.FileChannel;
import java.nio.channels.SocketChannel;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import xbird.util.datetime.StopWatch;
import xbird.util.io.FastByteArrayOutputStream;
import xbird.util.io.IOUtils;
import xbird.util.lang.PrintUtils;
import xbird.util.net.NetUtils;

/**
*
* <DIV lang="en"></DIV>
* <DIV lang="ja"></DIV>
*
* @author Makoto YUI (yuin405+xbird@gmail.com)
*/
public final class TransferUtils {
    private static final Log LOG = LogFactory.getLog(TransferUtils.class);

    private TransferUtils() {}

    public static void sendfile(@Nonnull final File file, @Nonnull final InetAddress dstAddr, final int dstPort, final boolean append, final boolean sync)
            throws IOException {
        sendfile(file, null, dstAddr, dstPort, append, sync);
    }

    public static void sendfile(@Nonnull final File file, @Nullable final String writeDirPath, @Nonnull final InetAddress dstAddr, final int dstPort, final boolean append, final boolean sync)
            throws IOException {
        sendfile(file, writeDirPath, dstAddr, dstPort, append, sync, null);
    }

    public static void sendfile(@Nonnull final File file, @Nullable final String writeDirPath, @Nonnull final InetAddress dstAddr, final int dstPort, final boolean append, final boolean sync, @Nonnull final TransferClientHandler handler)
            throws IOException {
        sendfile(file, 0L, -1L, writeDirPath, dstAddr, dstPort, append, sync, handler);
    }

    public static void sendfile(@Nonnull final File file, final long fromPos, final long count, @Nullable final String writeDirPath, @Nonnull final InetAddress dstAddr, final int dstPort, final boolean append, final boolean sync, @Nonnull final TransferClientHandler handler)
            throws IOException {
        if(!file.exists()) {
            throw new IllegalArgumentException(file.getAbsolutePath() + " does not exist");
        }
        if(!file.isFile()) {
            throw new IllegalArgumentException(file.getAbsolutePath() + " is not file");
        }
        if(!file.canRead()) {
            throw new IllegalArgumentException(file.getAbsolutePath() + " cannot read");
        }

        final SocketAddress dstSockAddr = new InetSocketAddress(dstAddr, dstPort);
        SocketChannel channel = null;
        Socket socket = null;
        final OutputStream out;
        try {
            channel = SocketChannel.open();
            socket = channel.socket();
            socket.connect(dstSockAddr);
            out = socket.getOutputStream();
        } catch (IOException e) {
            LOG.error("failed to connect: " + dstSockAddr, e);
            IOUtils.closeQuietly(channel);
            NetUtils.closeQuietly(socket);
            throw e;
        }

        DataInputStream din = null;
        if(sync) {
            InputStream in = socket.getInputStream();
            din = new DataInputStream(in);
        }
        final DataOutputStream dos = new DataOutputStream(out);
        final StopWatch sw = new StopWatch();
        FileInputStream src = null;
        final long nbytes;
        try {
            src = new FileInputStream(file);
            FileChannel fc = src.getChannel();

            String fileName = file.getName();
            IOUtils.writeString(fileName, dos);
            IOUtils.writeString(writeDirPath, dos);
            long xferBytes = (count == -1L) ? fc.size() : count;
            dos.writeLong(xferBytes);
            dos.writeBoolean(append); // append=false
            dos.writeBoolean(sync);
            if(handler == null) {
                dos.writeBoolean(false);
            } else {
                dos.writeBoolean(true);
                handler.writeAdditionalHeader(dos);
            }

            // send file using zero-copy send
            nbytes = fc.transferTo(fromPos, xferBytes, channel);
            if(LOG.isDebugEnabled()) {
                LOG.debug("Sent a file '" + file.getAbsolutePath() + "' of " + nbytes
                        + " bytes to " + dstSockAddr.toString() + " in " + sw.toString());
            }

            if(sync) {// receive ack in sync mode
                long remoteRecieved = din.readLong();
                if(remoteRecieved != xferBytes) {
                    throw new IllegalStateException("Sent " + xferBytes
                            + " bytes, but remote node received " + remoteRecieved + " bytes");
                }
            }

        } catch (FileNotFoundException e) {
            LOG.error(PrintUtils.prettyPrintStackTrace(e, -1));
            throw e;
        } catch (IOException e) {
            LOG.error(PrintUtils.prettyPrintStackTrace(e, -1));
            throw e;
        } finally {
            IOUtils.closeQuietly(src);
            IOUtils.closeQuietly(din, dos);
            IOUtils.closeQuietly(channel);
            NetUtils.closeQuietly(socket);
        }
    }

    public static void send(@Nonnull final FastByteArrayOutputStream data, @Nonnull final String fileName, @Nonnull final InetAddress dstAddr, final int dstPort, final boolean append, final boolean sync)
            throws IOException {
        send(data, fileName, null, dstAddr, dstPort, append, sync);
    }

    public static void send(@Nonnull final FastByteArrayOutputStream data, @Nonnull final String fileName, @Nullable final String writeDirPath, @Nonnull final InetAddress dstAddr, final int dstPort, final boolean append, final boolean sync)
            throws IOException {
        send(data, fileName, writeDirPath, dstAddr, dstPort, append, sync, null);
    }

    public static void send(@Nonnull final FastByteArrayOutputStream data, @Nonnull final String fileName, @Nullable final String writeDirPath, @Nonnull final InetAddress dstAddr, final int dstPort, final boolean append, final boolean sync, @Nullable final TransferClientHandler handler)
            throws IOException {
        final SocketAddress dstSockAddr = new InetSocketAddress(dstAddr, dstPort);
        SocketChannel channel = null;
        Socket socket = null;
        final OutputStream out;
        try {
            channel = SocketChannel.open();
            socket = channel.socket();
            socket.connect(dstSockAddr);
            out = socket.getOutputStream();
        } catch (IOException e) {
            LOG.error("failed to connect: " + dstSockAddr, e);
            IOUtils.closeQuietly(channel);
            NetUtils.closeQuietly(socket);
            throw e;
        }

        DataInputStream din = null;
        if(sync) {
            InputStream in = socket.getInputStream();
            din = new DataInputStream(in);
        }
        final DataOutputStream dos = new DataOutputStream(out);
        final StopWatch sw = new StopWatch();
        try {
            IOUtils.writeString(fileName, dos);
            IOUtils.writeString(writeDirPath, dos);
            long nbytes = data.size();
            dos.writeLong(nbytes);
            dos.writeBoolean(append);
            dos.writeBoolean(sync);
            if(handler == null) {
                dos.writeBoolean(false);
            } else {
                dos.writeBoolean(true);
                handler.writeAdditionalHeader(dos);
            }

            // send file using zero-copy send
            data.writeTo(out);

            if(LOG.isDebugEnabled()) {
                LOG.debug("Sent a file data '" + fileName + "' of " + nbytes + " bytes to "
                        + dstSockAddr.toString() + " in " + sw.toString());
            }

            if(sync) {// receive ack in sync mode
                long remoteRecieved = din.readLong();
                if(remoteRecieved != nbytes) {
                    throw new IllegalStateException("Sent " + nbytes
                            + " bytes, but remote node received " + remoteRecieved + " bytes");
                }
            }
        } catch (FileNotFoundException e) {
            LOG.error(PrintUtils.prettyPrintStackTrace(e, -1));
            throw e;
        } catch (IOException e) {
            LOG.error(PrintUtils.prettyPrintStackTrace(e, -1));
            throw e;
        } finally {
            IOUtils.closeQuietly(din, dos);
            IOUtils.closeQuietly(channel);
            NetUtils.closeQuietly(socket);
        }
    }

}
TOP

Related Classes of xbird.util.xfer.TransferUtils

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.