package com.limegroup.gnutella.archive; import java.io.IOException; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import com.limegroup.gnutella.FileDesc; import com.limegroup.gnutella.util.CoWList; abstract class AbstractContribution implements Contribution { private String _title; private String _description; private int _media; private int _collection; private int _type; private String _username, _password; private final LinkedHashMap _files = new LinkedHashMap(); /** String -> String */ private HashMap _fields = new HashMap(); private volatile boolean _cancelled; /** LOCKING: this */ private String _curFileName; private int _filesSent = 0; private long _totalBytesSent; protected long _totalUploadSize; protected final Map _fileNames2Progress = new HashMap(); private int _id = NOT_CONNECTED; private final List _uploadListeners = new CoWList(CoWList.ARRAY_LIST); /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#getVerificationUrl() */ abstract public String getVerificationUrl(); /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#requestIdentifier(java.lang.String) */ abstract public String requestIdentifier( String identifier ) throws IdentifierUnavailableException, IOException; /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#getIdentifier() */ abstract public String getIdentifier(); /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#upload() */ abstract public void upload() throws IOException; /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#addFileDesc(com.limegroup.gnutella.FileDesc) */ public void addFileDesc( FileDesc fd ) { _files.put( fd, new File(fd)); } /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#removeFileDesc(com.limegroup.gnutella.FileDesc) */ public void removeFileDesc( FileDesc fd ) { _files.remove( fd ); } /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#containsFileDesc(com.limegroup.gnutella.FileDesc) */ public boolean containsFileDesc( FileDesc fd ) { return _files.containsKey( fd ); } /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#cancel() */ public void cancel() { _cancelled = true; } boolean isCancelled() { return _cancelled; } /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#getFileDescs() */ public Set getFileDescs() { return Collections.unmodifiableSet( _files.keySet() ); } protected Collection getFiles() { return Collections.unmodifiableCollection(_files.values()); } /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#setTitle(java.lang.String) */ public void setTitle( String title ) { _title = title; } /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#getTitle() */ public String getTitle() { return _title; } public void setDescription( String description ) throws DescriptionTooShortException { _description = description; } public String getDescription() { return _description; } /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#setMedia(int) */ public void setMedia( int media ) { if ( Archives.getMediaString( media ) == null ) { throw new IllegalArgumentException( "Invalid media type: " + media ); } _media = media; } /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#getMedia() */ public int getMedia() { return _media; } /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#setCollection(int) */ public void setCollection( int collection ) { if ( Archives.getCollectionString( collection ) == null ) { throw new IllegalArgumentException( "Invalid collection type: " + collection ); } _collection = collection; } /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#getCollection() */ public int getCollection() { return _collection; } /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#setType(int) */ public void setType( int type ) { if (Archives.getTypeString( type ) == null ) { throw new IllegalArgumentException( "Invalid dublin-core type: " + type ); } _type = type; } /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#getType() */ public int getType() { return _type; } /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#getPassword() */ public String getPassword() { return _password; } /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#setPassword(java.lang.String) */ public void setPassword(String password) { _password = password; } /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#getUsername() */ public String getUsername() { return _username; } /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#setUsername(java.lang.String) */ public void setUsername(String username) { _username = username; } /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#setField(java.lang.String, java.lang.String) */ public void setField( String field, String value ) { _fields.put( field, value ); } /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#getField(java.lang.String) */ public String getField( String field ) { return (String) _fields.get( field ); } /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#removeField(java.lang.String) */ public void removeField( String field ) { _fields.remove( field ); } protected Map getFields() { return Collections.unmodifiableMap( _fields ); } protected class UploadFileProgress { private final long _fileSize; private long _bytesSent = 0; public UploadFileProgress( long fileSize ) { _fileSize = fileSize; } public long getFileSize() { return _fileSize; } public long getBytesSent() { return _bytesSent; } public void setBytesSent( long bytesSent ) { _bytesSent = bytesSent; } public void incrBytesSent( long bytesSentDelta ) { _bytesSent += bytesSentDelta; } } /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#addListener(com.limegroup.gnutella.archive.UploadListener) */ public void addListener( UploadListener l ) { _uploadListeners.add( l ); } /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#removeListener(com.limegroup.gnutella.archive.UploadListener) */ public void removeListener( UploadListener l ) { _uploadListeners.remove( l ); } private void notifyStateChange() { for (Iterator i = _uploadListeners.iterator(); i.hasNext();) { UploadListener l = (UploadListener) i.next(); switch ( _id ) { case FILE_STARTED: l.fileStarted(); break; case FILE_PROGRESSED: l.fileProgressed(); break; case FILE_COMPLETED: l.fileCompleted(); break; case CONNECTED: l.connected(); break; case CHECKIN_STARTED: l.checkinStarted(); break; case CHECKIN_COMPLETED: l.checkinCompleted(); break; default: break; } } } /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#getFilesSent() */ public synchronized int getFilesSent() { return _filesSent; } /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#getTotalFiles() */ public synchronized int getTotalFiles() { return _fileNames2Progress.size(); } /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#getFileBytesSent() */ public synchronized long getFileBytesSent() { return ((UploadFileProgress) _fileNames2Progress.get( _curFileName )).getBytesSent(); } /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#getFileSize() */ public synchronized long getFileSize() { return ((UploadFileProgress) _fileNames2Progress.get( _curFileName )).getFileSize(); } /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#getTotalBytesSent() */ public synchronized long getTotalBytesSent() { return _totalBytesSent; } /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#getTotalSize() */ public synchronized long getTotalSize() { return _totalUploadSize; } /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#getFileName() */ public synchronized String getFileName() { return _curFileName; } /* (non-Javadoc) * @see com.limegroup.gnutella.archive.Contribution#getID() */ public int getID() { return _id; } void connected() { _id = CONNECTED; } void fileStarted( String fileName, long bytesSent ) { _id = FILE_STARTED; synchronized(this) { _curFileName = fileName; ((UploadFileProgress) _fileNames2Progress.get( fileName )).setBytesSent( bytesSent ); } notifyStateChange(); } void fileStarted( String fileName ) { fileStarted( fileName, 0 ); } /** * * @param fileName * @param bytesSent * * @throws IllegalStateException * If fileName does not match the current fileName */ void fileProgressed( long bytesSent ) { _id = FILE_PROGRESSED; synchronized(this) { UploadFileProgress progress = (UploadFileProgress) _fileNames2Progress.get( _curFileName ); // find delta long delta = bytesSent - progress.getBytesSent(); _totalBytesSent += delta; progress.setBytesSent( bytesSent ); } notifyStateChange(); } /** * * @param fileName * @param bytesSentDelta * * @throws IllegalStateException * If fileName does not match the current fileName */ void fileProgressedDelta( long bytesSentDelta ) { _id = FILE_PROGRESSED; synchronized(this) { _totalBytesSent += bytesSentDelta; ((UploadFileProgress) _fileNames2Progress.get( _curFileName )).incrBytesSent( bytesSentDelta ); } notifyStateChange(); } /** * * @param fileName * * @throws IllegalStateException * If fileName does not match the current fileName */ void fileCompleted() { _id = FILE_COMPLETED; synchronized(this) { UploadFileProgress progress = (UploadFileProgress) _fileNames2Progress.get( _curFileName ); progress.setBytesSent( progress.getFileSize() ); _filesSent++; } notifyStateChange(); } void checkinStarted() { _id = CHECKIN_STARTED; notifyStateChange(); } void checkinCompleted() { _id = CHECKIN_COMPLETED; notifyStateChange(); } }