@ -39,25 +39,25 @@ import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ThreadFactory ;
import java.util.concurrent.ThreadFactory ;
import java.util.concurrent.TimeUnit ;
import java.util.concurrent.TimeUnit ;
import com.google.common.base.Predicate ;
import com.google.common.collect.Iterables ;
import com.google.common.collect.Lists ;
import org.apache.commons.io.FilenameUtils ;
import org.apache.commons.io.FilenameUtils ;
import org.apache.commons.io.IOUtils ;
import org.apache.commons.io.IOUtils ;
import org.apache.commons.lang.StringUtils ;
import org.apache.commons.lang.StringUtils ;
import org.apache.http.Header ;
import org.apache.http.Header ;
import org.apache.http.HttpResponse ;
import org.apache.http.HttpResponse ;
import org.apache.http.client.HttpClient ;
import org.apache.http.client.config.RequestConfig ;
import org.apache.http.client.methods.CloseableHttpResponse ;
import org.apache.http.client.methods.HttpGet ;
import org.apache.http.client.methods.HttpGet ;
import org.apache.http.entity.ContentType ;
import org.apache.http.entity.ContentType ;
import org.apache.http.impl.client.Default HttpClient ;
import org.apache.http.impl.client.Closeable HttpClient ;
import org.apache.http.params.HttpConnectionParam s ;
import org.apache.http.impl.client.HttpClient s ;
import org.jdom.Document ;
import org.jdom.Document ;
import org.jdom.Element ;
import org.jdom.Element ;
import org.jdom.Namespace ;
import org.jdom.Namespace ;
import org.jdom.input.SAXBuilder ;
import org.jdom.input.SAXBuilder ;
import com.google.common.base.Predicate ;
import com.google.common.collect.Iterables ;
import com.google.common.collect.Lists ;
import org.libresonic.player.Logger ;
import org.libresonic.player.Logger ;
import org.libresonic.player.dao.PodcastDao ;
import org.libresonic.player.dao.PodcastDao ;
import org.libresonic.player.domain.MediaFile ;
import org.libresonic.player.domain.MediaFile ;
@ -302,33 +302,34 @@ public class PodcastService {
@SuppressWarnings ( { "unchecked" } )
@SuppressWarnings ( { "unchecked" } )
private void doRefreshChannel ( PodcastChannel channel , boolean downloadEpisodes ) {
private void doRefreshChannel ( PodcastChannel channel , boolean downloadEpisodes ) {
InputStream in = null ;
InputStream in = null ;
HttpClient client = new DefaultHttpClient ( ) ;
try {
try ( CloseableHttpClient client = HttpClients . createDefault ( ) ) {
channel . setStatus ( PodcastStatus . DOWNLOADING ) ;
channel . setStatus ( PodcastStatus . DOWNLOADING ) ;
channel . setErrorMessage ( null ) ;
channel . setErrorMessage ( null ) ;
podcastDao . updateChannel ( channel ) ;
podcastDao . updateChannel ( channel ) ;
RequestConfig requestConfig = RequestConfig . custom ( )
HttpConnectionParams . setConnectionTimeout ( client . getParams ( ) , 2 * 60 * 1000 ) ; // 2 minutes
. setConnectTimeout ( 2 * 60 * 1000 ) // 2 minutes
HttpConnectionParams . setSoTimeout ( client . getParams ( ) , 10 * 60 * 1000 ) ; // 10 minutes
. setSocketTimeout ( 10 * 60 * 1000 ) // 10 minutes
. build ( ) ;
HttpGet method = new HttpGet ( channel . getUrl ( ) ) ;
HttpGet method = new HttpGet ( channel . getUrl ( ) ) ;
method . setConfig ( requestConfig ) ;
HttpResponse response = client . execute ( method ) ;
try ( CloseableHttpResponse response = client . execute ( method ) ) {
in = response . getEntity ( ) . getContent ( ) ;
in = response . getEntity ( ) . getContent ( ) ;
Document document = new SAXBuilder ( ) . build ( in ) ;
Element channelElement = document . getRootElement ( ) . getChild ( "channel" ) ;
channel . setTitle ( StringUtil . removeMarkup ( channelElement . getChildTextTrim ( "title" ) ) ) ;
Document document = new SAXBuilder ( ) . build ( in ) ;
channel . setDescription ( StringUtil . removeMarkup ( channelElement . getChildTextTrim ( "description" ) ) ) ;
Element channelElement = document . getRootElement ( ) . getChild ( "channel" ) ;
channel . setImageUrl ( getChannelImageUrl ( channelElement ) ) ;
channel . setStatus ( PodcastStatus . COMPLETED ) ;
channel . setErrorMessage ( null ) ;
podcastDao . updateChannel ( channel ) ;
downloadImage ( channel ) ;
channel . setTitle ( StringUtil . removeMarkup ( channelElement . getChildTextTrim ( "title" ) ) ) ;
refreshEpisodes ( channel , channelElement . getChildren ( "item" ) ) ;
channel . setDescription ( StringUtil . removeMarkup ( channelElement . getChildTextTrim ( "description" ) ) ) ;
channel . setImageUrl ( getChannelImageUrl ( channelElement ) ) ;
channel . setStatus ( PodcastStatus . COMPLETED ) ;
channel . setErrorMessage ( null ) ;
podcastDao . updateChannel ( channel ) ;
downloadImage ( channel ) ;
refreshEpisodes ( channel , channelElement . getChildren ( "item" ) ) ;
}
} catch ( Exception x ) {
} catch ( Exception x ) {
LOG . warn ( "Failed to get/parse RSS file for Podcast channel " + channel . getUrl ( ) , x ) ;
LOG . warn ( "Failed to get/parse RSS file for Podcast channel " + channel . getUrl ( ) , x ) ;
channel . setStatus ( PodcastStatus . ERROR ) ;
channel . setStatus ( PodcastStatus . ERROR ) ;
@ -336,7 +337,6 @@ public class PodcastService {
podcastDao . updateChannel ( channel ) ;
podcastDao . updateChannel ( channel ) ;
} finally {
} finally {
IOUtils . closeQuietly ( in ) ;
IOUtils . closeQuietly ( in ) ;
client . getConnectionManager ( ) . shutdown ( ) ;
}
}
if ( downloadEpisodes ) {
if ( downloadEpisodes ) {
@ -349,10 +349,9 @@ public class PodcastService {
}
}
private void downloadImage ( PodcastChannel channel ) {
private void downloadImage ( PodcastChannel channel ) {
HttpClient client = new DefaultHttpClient ( ) ;
InputStream in = null ;
InputStream in = null ;
OutputStream out = null ;
OutputStream out = null ;
try {
try ( CloseableHttpClient client = HttpClients . createDefault ( ) ) {
String imageUrl = channel . getImageUrl ( ) ;
String imageUrl = channel . getImageUrl ( ) ;
if ( imageUrl = = null ) {
if ( imageUrl = = null ) {
return ;
return ;
@ -367,17 +366,17 @@ public class PodcastService {
}
}
HttpGet method = new HttpGet ( imageUrl ) ;
HttpGet method = new HttpGet ( imageUrl ) ;
HttpResponse response = client . execute ( method ) ;
try ( CloseableHttpResponse response = client . execute ( method ) ) {
in = response . getEntity ( ) . getContent ( ) ;
in = response . getEntity ( ) . getContent ( ) ;
out = new FileOutputStream ( new File ( dir , "cover." + getCoverArtSuffix ( response ) ) ) ;
out = new FileOutputStream ( new File ( dir , "cover." + getCoverArtSuffix ( response ) ) ) ;
IOUtils . copy ( in , out ) ;
IOUtils . copy ( in , out ) ;
mediaFileService . refreshMediaFile ( channelMediaFile ) ;
mediaFileService . refreshMediaFile ( channelMediaFile ) ;
}
} catch ( Exception x ) {
} catch ( Exception x ) {
LOG . warn ( "Failed to download cover art for podcast channel '" + channel . getTitle ( ) + "': " + x , x ) ;
LOG . warn ( "Failed to download cover art for podcast channel '" + channel . getTitle ( ) + "': " + x , x ) ;
} finally {
} finally {
IOUtils . closeQuietly ( in ) ;
IOUtils . closeQuietly ( in ) ;
IOUtils . closeQuietly ( out ) ;
IOUtils . closeQuietly ( out ) ;
client . getConnectionManager ( ) . shutdown ( ) ;
}
}
}
}
@ -534,68 +533,69 @@ public class PodcastService {
LOG . info ( "Starting to download Podcast from " + episode . getUrl ( ) ) ;
LOG . info ( "Starting to download Podcast from " + episode . getUrl ( ) ) ;
HttpClient client = new DefaultHttpClient ( ) ;
try ( CloseableHttpClient client = HttpClients . createDefault ( ) ) {
try {
if ( ! settingsService . getLicenseInfo ( ) . isLicenseOrTrialValid ( ) ) {
if ( ! settingsService . getLicenseInfo ( ) . isLicenseOrTrialValid ( ) ) {
throw new Exception ( "Sorry, the trial period is expired." ) ;
throw new Exception ( "Sorry, the trial period is expired." ) ;
}
}
PodcastChannel channel = getChannel ( episode . getChannelId ( ) ) ;
PodcastChannel channel = getChannel ( episode . getChannelId ( ) ) ;
RequestConfig requestConfig = RequestConfig . custom ( )
HttpConnectionParams . setConnectionTimeout ( client . getParams ( ) , 2 * 60 * 1000 ) ; // 2 minutes
. setConnectTimeout ( 2 * 60 * 1000 ) // 2 minutes
HttpConnectionParams . setSoTimeout ( client . getParams ( ) , 10 * 60 * 1000 ) ; // 10 minutes
. setSocketTimeout ( 10 * 60 * 1000 ) // 10 minutes
. build ( ) ;
HttpGet method = new HttpGet ( episode . getUrl ( ) ) ;
HttpGet method = new HttpGet ( episode . getUrl ( ) ) ;
method . setConfig ( requestConfig ) ;
HttpResponse response = client . execute ( method ) ;
try ( Closeable HttpResponse response = client . execute ( method ) ) {
in = response . getEntity ( ) . getContent ( ) ;
in = response . getEntity ( ) . getContent ( ) ;
File file = getFile ( channel , episode ) ;
File file = getFile ( channel , episode ) ;
out = new FileOutputStream ( file ) ;
out = new FileOutputStream ( file ) ;
episode . setStatus ( PodcastStatus . DOWNLOADING ) ;
episode . setStatus ( PodcastStatus . DOWNLOADING ) ;
episode . setBytesDownloaded ( 0L ) ;
episode . setBytesDownloaded ( 0L ) ;
episode . setErrorMessage ( null ) ;
episode . setErrorMessage ( null ) ;
episode . setPath ( file . getPath ( ) ) ;
episode . setPath ( file . getPath ( ) ) ;
podcastDao . updateEpisode ( episode ) ;
podcastDao . updateEpisode ( episode ) ;
byte [ ] buffer = new byte [ 4096 ] ;
byte [ ] buffer = new byte [ 4096 ] ;
long bytesDownloaded = 0 ;
long bytesDownloaded = 0 ;
int n ;
int n ;
long nextLogCount = 30000L ;
long nextLogCount = 30000L ;
while ( ( n = in . read ( buffer ) ) ! = - 1 ) {
while ( ( n = in . read ( buffer ) ) ! = - 1 ) {
out . write ( buffer , 0 , n ) ;
out . write ( buffer , 0 , n ) ;
bytesDownloaded + = n ;
bytesDownloaded + = n ;
if ( bytesDownloaded > nextLogCount ) {
if ( bytesDownloaded > nextLogCount ) {
episode . setBytesDownloaded ( bytesDownloaded ) ;
episode . setBytesDownloaded ( bytesDownloaded ) ;
nextLogCount + = 30000L ;
nextLogCount + = 30000L ;
// Abort download if episode was deleted by user.
// Abort download if episode was deleted by user.
if ( isEpisodeDeleted ( episode ) ) {
if ( isEpisodeDeleted ( episode ) ) {
break ;
break ;
}
podcastDao . updateEpisode ( episode ) ;
}
}
podcastDao . updateEpisode ( episode ) ;
}
}
}
if ( isEpisodeDeleted ( episode ) ) {
if ( isEpisodeDeleted ( episode ) ) {
LOG . info ( "Podcast " + episode . getUrl ( ) + " was deleted. Aborting download." ) ;
LOG . info ( "Podcast " + episode . getUrl ( ) + " was deleted. Aborting download." ) ;
IOUtils . closeQuietly ( out ) ;
IOUtils . closeQuietly ( out ) ;
file . delete ( ) ;
file . delete ( ) ;
} else {
} else {
addMediaFileIdToEpisodes ( Arrays . asList ( episode ) ) ;
addMediaFileIdToEpisodes ( Arrays . asList ( episode ) ) ;
episode . setBytesDownloaded ( bytesDownloaded ) ;
episode . setBytesDownloaded ( bytesDownloaded ) ;
podcastDao . updateEpisode ( episode ) ;
podcastDao . updateEpisode ( episode ) ;
LOG . info ( "Downloaded " + bytesDownloaded + " bytes from Podcast " + episode . getUrl ( ) ) ;
LOG . info ( "Downloaded " + bytesDownloaded + " bytes from Podcast " + episode . getUrl ( ) ) ;
IOUtils . closeQuietly ( out ) ;
IOUtils . closeQuietly ( out ) ;
updateTags ( file , episode ) ;
updateTags ( file , episode ) ;
episode . setStatus ( PodcastStatus . COMPLETED ) ;
episode . setStatus ( PodcastStatus . COMPLETED ) ;
podcastDao . updateEpisode ( episode ) ;
podcastDao . updateEpisode ( episode ) ;
deleteObsoleteEpisodes ( channel ) ;
deleteObsoleteEpisodes ( channel ) ;
}
}
}
} catch ( Exception x ) {
} catch ( Exception x ) {
LOG . warn ( "Failed to download Podcast from " + episode . getUrl ( ) , x ) ;
LOG . warn ( "Failed to download Podcast from " + episode . getUrl ( ) , x ) ;
episode . setStatus ( PodcastStatus . ERROR ) ;
episode . setStatus ( PodcastStatus . ERROR ) ;
@ -604,7 +604,6 @@ public class PodcastService {
} finally {
} finally {
IOUtils . closeQuietly ( in ) ;
IOUtils . closeQuietly ( in ) ;
IOUtils . closeQuietly ( out ) ;
IOUtils . closeQuietly ( out ) ;
client . getConnectionManager ( ) . shutdown ( ) ;
}
}
}
}