Package net.sf.gimme

Source Code of net.sf.gimme.Segment

/*
* Segment.java 
*
* Copyright (C) 2008 Gimme
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package net.sf.gimme;

import net.sf.gimme.event.Mediator;
import net.sf.gimme.event.SegmentFinished;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.URL;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.net.ftp.FTPClient;

/**
*
* @author aiden
*/
public class Segment implements Runnable
{
    private Download download;
    private URL url;
    private int index;
    private long offset = 0;
    private File tempFile;
    private boolean paused;
    private long speed = 0;
    private FTPClient ftp = new FTPClient();

    public boolean isFinished()
    {
        return finished;
    }
    private boolean finished;

    public Segment(Download download, int index)
    {
        this.download = download;
        this.url = download.getUrl();
        this.index = index;

        init();
    }

    public Segment(Download download, URL url, int index)
    {
        this.download = download;
        this.url = url;
        this.index = index;

        init();
    }

    private void init()
    {
        tempFile = new File(download.getTempFolder(), download.getName() + "." + index);

        offset = (long)Math.ceil((float)download.getTotalSize() / (float)download.getSegments().length) * index;

        Thread thread = new Thread(this);
        thread.setDaemon(true);
        thread.start();
    }

    private InputStream urlToInputStream(URL url)
            throws IOException
    {
        InputStream is = url.openStream();

        if(url.getProtocol().toLowerCase().equals("http"))
        {
            try
            {
                HttpClient http = new HttpClient();
                HttpMethod method = new GetMethod(url.toString());
                http.executeMethod(method);

                is = method.getResponseBodyAsStream();

                if(is == null)
                {
                    throw new NullPointerException();
                }
            }
            catch(Exception ex)
            {
                Logger.post(Logger.Level.WARNING, "Use of Jakarta HttpClient failed. Trying another solution...");
            }
        }
        else if(url.getProtocol().toLowerCase().equals("ftp"))
        {
            //TODO: somehow use FTPClient
        }

        return is;
    }

    public void run()
    {
        Segment[] segs = download.getSegments();

        while(segs[segs.length - 1] == null)
        {
            Thread.yield();
        }

        try
        {
            long downloaded = tempFile.length();

            RandomAccessFile rw = new RandomAccessFile(tempFile, "rw");

            InputStream in = urlToInputStream(url);

            long limit = offset;

            if(index + 1 < segs.length)
            {
                limit = segs[index + 1].getOffset();
            }
            else
            {
                limit = download.getTotalSize();
            }

            rw.seek(downloaded);
            download.incrementSize(downloaded);

            long pos = offset + downloaded;

            //This loop makes sure that skip() actually works correctly
            //Without it, sometimes not enough bytes are skipped in the
            //input stream
            long skipped = 0;

            while(skipped < pos)
            {
                skipped += in.skip(pos - skipped);
            }


            long time = System.currentTimeMillis();
            long oldPos = pos;

            final int CHUNK_SIZE = 16384;

            while(pos < limit)
            {
                byte buffer[];
                if(limit - pos > CHUNK_SIZE)
                {
                    buffer = new byte[CHUNK_SIZE];
                }
                else
                {
                    buffer = new byte[(int)(limit - pos)];
                }

                int read = in.read(buffer);
                if(read == -1)
                {
                    break;
                }

                rw.write(buffer, 0, read);

                pos += read;
                download.incrementSize(read);

                if(System.currentTimeMillis() - time >= 1000)
                {
                    speed = pos - oldPos;
                    oldPos = pos;
                    time = System.currentTimeMillis();
                }

                while(paused)
                {
                    Thread.yield();
                }
            }

            rw.close();
            in.close();

            if(ftp.isConnected())
            {
                ftp.disconnect();
            }

            finished = true;
            Mediator.post(new SegmentFinished(this));
        }
        catch(IOException ex)
        {
            ex.printStackTrace();
        }
    }

    public long getOffset()
    {
        return offset;
    }

    public File getTempFile()
    {
        return tempFile;
    }

    void pause()
    {
        paused = true;
    }

    void resume()
    {
        paused = false;
    }

    public long getSpeed()
    {
        return speed;
    }
}
TOP

Related Classes of net.sf.gimme.Segment

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.