// BlogBridge -- RSS feed reader, manager, and web based service
// Copyright (C) 2002-2006 by R. Pito Salas
//
// 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place,
// Suite 330, Boston, MA 02111-1307 USA
//
// Contact: R. Pito Salas
// mailto:pitosalas@users.sourceforge.net
// More information: about BlogBridge
// http://www.blogbridge.com
// http://sourceforge.net/projects/blogbridge
//
// $Id: NetTask.java,v 1.7 2006/05/29 12:48:30 spyromus Exp $
//
package com.salas.bb.networking.manager;
import com.salas.bb.utils.net.URLInputStream;
import com.salas.bb.utils.net.IStreamProgressListener;
import com.salas.bb.utils.i18n.Strings;
import java.util.Date;
import java.util.logging.Logger;
import java.util.logging.Level;
import java.net.URL;
import java.io.IOException;
import java.beans.PropertyChangeSupport;
import java.beans.PropertyChangeListener;
/**
* Simple handle for network task.
*/
public class NetTask
{
private static final Logger LOG = Logger.getLogger(NetTask.class.getName());
/** Connecting to the source. */
public static final int STATUS_CONNECTING = 0;
/** Task is actively running. */
public static final int STATUS_RUNNING = 1;
/** Task is pausing. */
public static final int STATUS_PAUSING = 2;
/** Task is on pause. */
public static final int STATUS_PAUSED = 3;
/** Task is unpausing. */
public static final int STATUS_UNPAUSING = 4;
/** Task has been successfully completed. */
public static final int STATUS_COMPLETED = 5;
/** Task has been aborted by used. */
public static final int STATUS_ABORTED = 6;
/** Task has beed errored. */
public static final int STATUS_ERRORED = 7;
private final URLInputStream stream;
private NetTaskGroup parent;
private String title;
private String parentFeed;
private int status;
protected Date startTime;
private float progress;
private long size;
private long read;
protected PropertyChangeSupport pcs = new PropertyChangeSupport(this);
/**
* Creates task.
*
* @param title title of the task.
*/
protected NetTask(String title)
{
this(title, null, null);
}
/**
* Creates task.
*
* @param aTitle title.
* @param aParentFeed owner feed.
* @param aStream stream.
*/
public NetTask(String aTitle, String aParentFeed, URLInputStream aStream)
{
this.title = aTitle;
this.parentFeed = aParentFeed;
this.stream = aStream;
this.startTime = new Date();
this.progress = -1;
this.size = -1;
this.read = 0;
this.status = STATUS_CONNECTING;
if (aStream != null)
{
aStream.addListener(new StreamListener());
}
}
/**
* Returns the title.
*
* @return title.
*/
public String getTitle()
{
return title;
}
/**
* Returns string representation.
*
* @return string representation.
*/
public String toString()
{
return title;
}
/**
* Returns task progress.
*
* @return progress.
*/
public float getProgress()
{
return progress;
}
/**
* Returns size of resource being fetched.
*
* @return size.
*/
public long getSize()
{
return size;
}
/**
* Returns time of activity start.
*
* @return time.
*/
public Date getStartTime()
{
return startTime;
}
/**
* Returns source URL of resource.
*
* @return URL.
*/
public URL getSourceURL()
{
return stream == null ? null : stream.getSourceURL();
}
/**
* Returns parent feed name (if any).
*
* @return parent feed name.
*/
public String getFeed()
{
return parentFeed;
}
/**
* Pauses the stream.
*/
public synchronized void pause()
{
if (stream != null)
{
setStatus(STATUS_PAUSING);
Thread thread = new Thread()
{
public void run()
{
stream.setPaused(true);
setStatus(STATUS_PAUSED);
}
};
thread.start();
}
}
/**
* Resumes the stream.
*/
public synchronized void resume()
{
if (stream != null)
{
setStatus(STATUS_UNPAUSING);
Thread thread = new Thread()
{
public void run()
{
stream.setPaused(false);
setStatus(STATUS_RUNNING);
}
};
thread.start();
}
}
/**
* Closes the stream.
*/
public void abort()
{
if (stream != null)
{
setStatus(STATUS_ABORTED);
try
{
stream.close();
} catch (IOException e)
{
LOG.log(Level.WARNING, Strings.error("net.failed.to.abort.the.stream"), e);
}
}
}
/**
* Sets the status.
*
* @param aStatus new status.
*/
private void setStatus(int aStatus)
{
int oldStatus = status;
status = aStatus;
pcs.firePropertyChange("status", oldStatus, status);
}
/**
* Returns the status of task.
*
* @return status.
*/
public int getStatus()
{
return status;
}
/**
* Sets the size of resource.
*
* @param aSize size.
*/
private void setSize(long aSize)
{
long oldSize = size;
size = aSize;
pcs.firePropertyChange("size", new Long(oldSize), new Long(size));
}
/**
* Sets the number of bytes read (updates progress).
*
* @param aRead bytes read.
*/
private void addRead(long aRead)
{
if (size > 0 && aRead > 0)
{
read += aRead;
setProgress(Math.min((float)read / size, 1));
}
}
/**
* Sets the progress of reading operation.
*
* @param aProgress progress.
*/
private void setProgress(float aProgress)
{
float oldProgress = progress;
progress = aProgress >= 0 ? aProgress * 100 : aProgress;
pcs.firePropertyChange("progress", new Float(oldProgress), new Float(progress));
}
// ---------------------------------------------------------------------------------------------
/**
* Adds property change listener.
*
* @param l listener.
*/
public void addPropertyChangeListener(PropertyChangeListener l)
{
pcs.addPropertyChangeListener(l);
}
/**
* Removes property change listener.
*
* @param l listener.
*/
public void removePropertyChangeListener(PropertyChangeListener l)
{
pcs.removePropertyChangeListener(l);
}
/**
* Returns all registered property change listeners.
*
* @return listeners.
*/
protected PropertyChangeListener[] getPropertyChangeListeners()
{
return pcs.getPropertyChangeListeners();
}
/**
* Returns parent of this task.
*
* @return parent.
*/
public NetTaskGroup getParent()
{
return parent;
}
/**
* Sets parent of this task.
*
* @param aParent parent.
*/
public void setParent(NetTaskGroup aParent)
{
parent = aParent;
}
// ---------------------------------------------------------------------------------------------
/** Listener of stream events. */
private class StreamListener implements IStreamProgressListener
{
/**
* Indicates the the source is being connected.
*
* @param source source.
*/
public void connecting(URLInputStream source)
{
setStatus(STATUS_CONNECTING);
}
/**
* Indicates that the source has been successfully connected.
*
* @param source source.
* @param length length of the resource (-1 if unknown).
*/
public void connected(URLInputStream source, long length)
{
// we don't change the status here as we don't know if we are running
// or paused or errored.
setSize(length);
setProgress(length == -1 ? -1 : 0);
}
/**
* Indicates that some bytes has been read.
*
* @param source source.
* @param bytes bytes.
*/
public void read(URLInputStream source, long bytes)
{
setStatus(STATUS_RUNNING);
addRead(bytes);
}
/**
* Indicates that the stream has been finished.
*
* @param source source.
*/
public void finished(URLInputStream source)
{
setProgress(1);
setStatus(STATUS_COMPLETED);
}
/**
* Indicates that there's an error happened during reading of stream. (We already did attempts
* to recover).
*
* @param source source.
* @param ex cause of error.
*/
public void errored(URLInputStream source, IOException ex)
{
setStatus(STATUS_ERRORED);
}
}
}