|  |  | @ -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.DefaultHttpClient; |  |  |  | import org.apache.http.impl.client.CloseableHttpClient; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | import org.apache.http.params.HttpConnectionParams; |  |  |  | import org.apache.http.impl.client.HttpClients; | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 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,18 +302,19 @@ 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); |  |  |  |                 Document document = new SAXBuilder().build(in); | 
			
		
	
	
		
		
			
				
					|  |  | @ -328,7 +329,7 @@ public class PodcastService { | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |                 downloadImage(channel); |  |  |  |                 downloadImage(channel); | 
			
		
	
		
		
			
				
					
					|  |  |  |                 refreshEpisodes(channel, channelElement.getChildren("item")); |  |  |  |                 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,20 +533,21 @@ 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 (CloseableHttpResponse response = client.execute(method)) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |                 in = response.getEntity().getContent(); |  |  |  |                 in = response.getEntity().getContent(); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |                 File file = getFile(channel, episode); |  |  |  |                 File file = getFile(channel, episode); | 
			
		
	
	
		
		
			
				
					|  |  | @ -595,7 +595,7 @@ public class PodcastService { | 
			
		
	
		
		
			
				
					
					|  |  |  |                     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(); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | 
 |