Package com.pugh.sockso.web.action

Source Code of com.pugh.sockso.web.action.Downloader

/*
* Downloader.java
*
* Allows downloading of single files, or multiple files packed
* up into zip archives.
*/

package com.pugh.sockso.web.action;

import com.pugh.sockso.Constants;
import com.pugh.sockso.Properties;
import com.pugh.sockso.Utils;
import com.pugh.sockso.db.Database;
import com.pugh.sockso.music.Track;
import com.pugh.sockso.resources.Locale;
import com.pugh.sockso.web.BadRequestException;
import com.pugh.sockso.web.Request;
import com.pugh.sockso.web.Response;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.apache.log4j.Logger;

public class Downloader extends BaseAction {
   
    private static final String VARIOUS_ARTISTS = "various_artists";
    private static final String VARIOUS_ALBUMS = "various_albums";

    private static final String DEFAULT_ARTIST = "artist";
    private static final String DEFAULT_ALBUM = "album";
   
    private static final Logger log = Logger.getLogger( Downloader.class );

    /**
     *  handles the "download" command.  allows the downloading of single files
     *  or multiple files in archives
     *
     *  @param req the request object
     *  @param res the response object
     *  @param user current user
     *
     *  @throws SQLException
     *  @throws IOException
     *  @throws BadRequestException
     *
     */
   
    public void handleRequest() throws SQLException, IOException, BadRequestException {

        final Request req = getRequest();
        final Response res = getResponse();
        final Locale locale = getLocale();
        final Properties p = getProperties();

        if ( p.get(Constants.WWW_DOWNLOADS_DISABLE).equals(Properties.YES) )
            throw new BadRequestException( locale.getString("www.error.downloadsDisabled"), 403 );
       
        final Database db = getDatabase();
        final String[] args = req.getPlayParams( false );
        final List<Track> tracks = Track.getTracksFromPlayArgs( db, args );
        final String fileName = getFileName( tracks );

        res.addHeader( "Content-length", Long.toString(getContentLength(tracks)) );
        res.addHeader( "Content-type", "application/zip" );
        res.addHeader( "Content-Disposition", "inline; filename=\"" + fileName + "\"" );
        res.sendHeaders();
        ZipOutputStream zip = null;
       
        try {
           
            zip = new ZipOutputStream( res.getOutputStream() );

            for ( final Track track : tracks )
                addTrackToZip( zip, track );

        }

        finally {
            if ( zip != null ) {
                zip.close();
            }
        }
       
    }
   
    /**
     *  returns the size in bytes of all the tracks in the list
     *
     *  @param tracks the tracks to get the size for
     *  @return the total size
     *
     */
   
    private long getContentLength( final List<Track> tracks ) {
       
        long total = 0;
       
        for ( final Track track : tracks )
            total += new File(track.getPath()).length();

        return total;
       
    }
   
    /**
     *  adds the specified track to the zip archive
     *
     *  @param zip the archive to add to
     *  @param track the track to add
     *
     *  @throws IOException
     *
     */
   
    private void addTrackToZip( final ZipOutputStream zip, final Track track ) throws IOException {

        final byte[] buf = new byte[4096];
        int retval;

        FileInputStream is = null;
       
        try {

            // entries are named by artist/album/number - track.ext
            final String name = getTrackZipPath( track );
            is = new FileInputStream(track.getPath());
            zip.putNextEntry( new ZipEntry(name) );

            do {
                retval = is.read( buf, 0, 4096 );
                if ( retval != -1 )
                    zip.write( buf, 0, retval );
            }
            while ( retval != -1 );

            zip.closeEntry();
           
        }

        finally { Utils.close(is); }
       
    }

    /**
     *  returns the path to use in the zip file for this track
     *
     *  @param track
     *
     *  @return
     *
     */
   
    protected String getTrackZipPath( final Track track ) {
       
        final int number = track.getNumber();

        return track.getArtist().getName() + "/" +
                    track.getAlbum().getName() + "/" +
                    (number == 0 ? "" : padTens(number) + " - ") +
                    track.getName() + "." + Utils.getExt(track.getPath());

    }
   
    /**
     *  pads numbers less than 10 with a leading 0.  if things
     *  go wrong then the number is returned
     *
     *  @param number the number to pad
     *  @return the padded number
     *
     */
   
    private String padTens( final int number ) {
       
        final String strNum = Integer.toString( number );
       
        return number < 10 ? "0" + strNum : strNum;
       
    }

    /**
     *  If all the tracks have the same artist, then append the artist name for
     *  the beginning of the file.  Otherwise, if there are different artists
     *  append VARIOUS_ARTISTS.  Then append the album name if all the tracks
     *  are from the same album, otherwise use VARIOUS_ALBUMS
     *
     *  @param tracks list of tracks
     *
     *  @return the name of the downloadable zip file - format: <artist>-<album>.zip
     *
     */

    protected String getFileName( final List<Track> tracks ) {

        return getArtistName( tracks ) +
               "-" +
               getAlbumName( tracks ) +
               ".zip";
       
    }

    /**
     *  Returns the artist name to use from the track
     *
     *  @param track Track
     *
     *  @TODO this is *so* similar to getAlbumName()
     *
     *  @return the String value of the artist's name.  Empty String if no name exists.
     *
     */

    private String getArtistName( final List<Track> tracks ) {

        String previousArtist = null;

        for ( final Track track : tracks ) {

            final String artistName = track.getArtist().getName();

            if ( previousArtist != null && !artistName.equalsIgnoreCase(previousArtist) ) {
                return VARIOUS_ARTISTS;
            }

            previousArtist = artistName;

        }

        return tracks.isEmpty()
            ? DEFAULT_ARTIST
            : tracks.get(0).getArtist().getName();

    }

    /**
     *  Returns the album name to use.  If all tracks are on the same album
     *  then returns album name, otherwise returns VARIOUS_ALBUMS
     *
     *  @param track Track
     *
     *  @TODO this is *so* similar to getArtistName()
     *
     *  @return the String value of the album's name.  "album" if no name exists.
     *
     */
   
    private String getAlbumName( final List<Track> tracks ) {

        String previousAlbum = null;

        for ( final Track track : tracks ) {

            final String albumName = track.getAlbum().getName();

            if ( previousAlbum != null && !albumName.equalsIgnoreCase(previousAlbum) ) {
                return VARIOUS_ALBUMS;
            }

            previousAlbum = albumName;
           
        }

        return tracks.isEmpty()
            ? DEFAULT_ALBUM
            : tracks.get(0).getAlbum().getName();

    }
   
}
TOP

Related Classes of com.pugh.sockso.web.action.Downloader

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.