From a1a18f77a50804e0127dfa4b0f5240c49c541184 Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Mon, 2 Jul 2012 21:24:02 -0700 Subject: Initial Commit --- .../subsonic/service/VersionService.java | 267 +++++++++++++++++++++ 1 file changed, 267 insertions(+) create mode 100644 subsonic-main/src/main/java/net/sourceforge/subsonic/service/VersionService.java (limited to 'subsonic-main/src/main/java/net/sourceforge/subsonic/service/VersionService.java') diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/service/VersionService.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/service/VersionService.java new file mode 100644 index 00000000..e24e6409 --- /dev/null +++ b/subsonic-main/src/main/java/net/sourceforge/subsonic/service/VersionService.java @@ -0,0 +1,267 @@ +/* + This file is part of Subsonic. + + Subsonic 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 3 of the License, or + (at your option) any later version. + + Subsonic 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 Subsonic. If not, see . + + Copyright 2009 (C) Sindre Mehus + */ +package net.sourceforge.subsonic.service; + +import net.sourceforge.subsonic.Logger; +import net.sourceforge.subsonic.domain.Version; +import org.apache.commons.io.IOUtils; +import org.apache.http.client.HttpClient; +import org.apache.http.client.ResponseHandler; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.BasicResponseHandler; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.params.HttpConnectionParams; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringReader; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Provides version-related services, including functionality for determining whether a newer + * version of Subsonic is available. + * + * @author Sindre Mehus + */ +public class VersionService { + + private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMdd"); + private static final Logger LOG = Logger.getLogger(VersionService.class); + + private Version localVersion; + private Version latestFinalVersion; + private Version latestBetaVersion; + private Date localBuildDate; + private String localBuildNumber; + + /** + * Time when latest version was fetched (in milliseconds). + */ + private long lastVersionFetched; + + /** + * Only fetch last version this often (in milliseconds.). + */ + private static final long LAST_VERSION_FETCH_INTERVAL = 7L * 24L * 3600L * 1000L; // One week + + /** + * URL from which to fetch latest versions. + */ + private static final String VERSION_URL = "http://subsonic.org/backend/version.view"; + + /** + * Returns the version number for the locally installed Subsonic version. + * + * @return The version number for the locally installed Subsonic version. + */ + public synchronized Version getLocalVersion() { + if (localVersion == null) { + try { + localVersion = new Version(readLineFromResource("/version.txt")); + LOG.info("Resolved local Subsonic version to: " + localVersion); + } catch (Exception x) { + LOG.warn("Failed to resolve local Subsonic version.", x); + } + } + return localVersion; + } + + /** + * Returns the version number for the latest available Subsonic final version. + * + * @return The version number for the latest available Subsonic final version, or null + * if the version number can't be resolved. + */ + public synchronized Version getLatestFinalVersion() { + refreshLatestVersion(); + return latestFinalVersion; + } + + /** + * Returns the version number for the latest available Subsonic beta version. + * + * @return The version number for the latest available Subsonic beta version, or null + * if the version number can't be resolved. + */ + public synchronized Version getLatestBetaVersion() { + refreshLatestVersion(); + return latestBetaVersion; + } + + /** + * Returns the build date for the locally installed Subsonic version. + * + * @return The build date for the locally installed Subsonic version, or null + * if the build date can't be resolved. + */ + public synchronized Date getLocalBuildDate() { + if (localBuildDate == null) { + try { + String date = readLineFromResource("/build_date.txt"); + localBuildDate = DATE_FORMAT.parse(date); + } catch (Exception x) { + LOG.warn("Failed to resolve local Subsonic build date.", x); + } + } + return localBuildDate; + } + + /** + * Returns the build number for the locally installed Subsonic version. + * + * @return The build number for the locally installed Subsonic version, or null + * if the build number can't be resolved. + */ + public synchronized String getLocalBuildNumber() { + if (localBuildNumber == null) { + try { + localBuildNumber = readLineFromResource("/build_number.txt"); + } catch (Exception x) { + LOG.warn("Failed to resolve local Subsonic build number.", x); + } + } + return localBuildNumber; + } + + /** + * Returns whether a new final version of Subsonic is available. + * + * @return Whether a new final version of Subsonic is available. + */ + public boolean isNewFinalVersionAvailable() { + Version latest = getLatestFinalVersion(); + Version local = getLocalVersion(); + + if (latest == null || local == null) { + return false; + } + + return local.compareTo(latest) < 0; + } + + /** + * Returns whether a new beta version of Subsonic is available. + * + * @return Whether a new beta version of Subsonic is available. + */ + public boolean isNewBetaVersionAvailable() { + Version latest = getLatestBetaVersion(); + Version local = getLocalVersion(); + + if (latest == null || local == null) { + return false; + } + + return local.compareTo(latest) < 0; + } + + /** + * Reads the first line from the resource with the given name. + * + * @param resourceName The resource name. + * @return The first line of the resource. + */ + private String readLineFromResource(String resourceName) { + InputStream in = VersionService.class.getResourceAsStream(resourceName); + if (in == null) { + return null; + } + BufferedReader reader = null; + try { + + reader = new BufferedReader(new InputStreamReader(in)); + return reader.readLine(); + + } catch (IOException x) { + return null; + } finally { + IOUtils.closeQuietly(reader); + IOUtils.closeQuietly(in); + } + } + + /** + * Refreshes the latest final and beta versions. + */ + private void refreshLatestVersion() { + long now = System.currentTimeMillis(); + boolean isOutdated = now - lastVersionFetched > LAST_VERSION_FETCH_INTERVAL; + + if (isOutdated) { + try { + lastVersionFetched = now; + readLatestVersion(); + } catch (Exception x) { + LOG.warn("Failed to resolve latest Subsonic version.", x); + } + } + } + + /** + * Resolves the latest available Subsonic version by screen-scraping a web page. + * + * @throws IOException If an I/O error occurs. + */ + private void readLatestVersion() throws IOException { + + HttpClient client = new DefaultHttpClient(); + HttpConnectionParams.setConnectionTimeout(client.getParams(), 10000); + HttpConnectionParams.setSoTimeout(client.getParams(), 10000); + HttpGet method = new HttpGet(VERSION_URL + "?v=" + getLocalVersion()); + String content; + try { + + ResponseHandler responseHandler = new BasicResponseHandler(); + content = client.execute(method, responseHandler); + + } finally { + client.getConnectionManager().shutdown(); + } + + BufferedReader reader = new BufferedReader(new StringReader(content)); + Pattern finalPattern = Pattern.compile("SUBSONIC_FULL_VERSION_BEGIN(.*)SUBSONIC_FULL_VERSION_END"); + Pattern betaPattern = Pattern.compile("SUBSONIC_BETA_VERSION_BEGIN(.*)SUBSONIC_BETA_VERSION_END"); + + try { + String line = reader.readLine(); + while (line != null) { + Matcher finalMatcher = finalPattern.matcher(line); + if (finalMatcher.find()) { + latestFinalVersion = new Version(finalMatcher.group(1)); + LOG.info("Resolved latest Subsonic final version to: " + latestFinalVersion); + } + Matcher betaMatcher = betaPattern.matcher(line); + if (betaMatcher.find()) { + latestBetaVersion = new Version(betaMatcher.group(1)); + LOG.info("Resolved latest Subsonic beta version to: " + latestBetaVersion); + } + line = reader.readLine(); + } + + } finally { + reader.close(); + } + } +} \ No newline at end of file -- cgit v1.2.3