123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- /*
- * Copyright (c) 2006-2017 DMDirc Developers
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
- * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
- * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
- package com.dmdirc.updater.checking;
-
- import com.dmdirc.config.binding.ConfigBinding;
- import com.dmdirc.config.GlobalConfig;
- import com.dmdirc.config.provider.AggregateConfigProvider;
- import com.dmdirc.updater.UpdateChannel;
- import com.dmdirc.updater.UpdateComponent;
- import com.dmdirc.updater.Version;
- import com.dmdirc.util.io.Downloader;
- import com.google.common.base.MoreObjects;
- import com.google.gson.Gson;
- import com.google.gson.reflect.TypeToken;
- import java.io.IOException;
- import java.net.MalformedURLException;
- import java.net.URL;
- import java.util.Collection;
- import java.util.Collections;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import java.util.Objects;
- import java.util.function.Function;
- import java.util.regex.Matcher;
- import java.util.regex.Pattern;
- import java.util.stream.Collectors;
- import javax.inject.Inject;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
-
- /**
- * Nightly update checker.
- */
- public class NightlyChecker implements UpdateCheckStrategy {
-
- private static final Logger LOG = LoggerFactory.getLogger(NightlyChecker.class);
- /** Name matching regex. */
- private final Pattern pattern = Pattern.compile(
- "^(.*?)-([^-]+(-[0-9]+-g[0-9a-f]+)?)(-SNAPSHOT)?\\.jar$");
- /** The URL to request to check for updates. */
- private static final String UPDATE_URL = "https://nightlies.dmdirc.com/json/latest";
- /** The update channel to check for updates on. */
- private UpdateChannel channel;
- /** Downloader to download files. */
- private final Downloader downloader;
-
- /**
- * Creates a new instance of {@link NightlyChecker}.
- *
- * @param configProvider The provider to use to retrieve update channel information.
- * @param downloader Used to download files
- */
- @Inject
- public NightlyChecker(@GlobalConfig final AggregateConfigProvider configProvider,
- final Downloader downloader) {
- configProvider.getBinder().bind(this, NightlyChecker.class);
- this.downloader = downloader;
- }
-
- /**
- * Sets the channel which will be used by the {@link NightlyChecker}.
- *
- * @param channel The new channel to use
- */
- @ConfigBinding(domain = "updater", key = "channel")
- public void setChannel(final String channel) {
- LOG.info("Changing channel to {}", channel);
- try {
- this.channel = UpdateChannel.valueOf(channel.toUpperCase());
- } catch (IllegalArgumentException ex) {
- this.channel = null;
- LOG.warn("Unknown channel {}", channel, ex);
- }
- }
-
- @Override
- public Map<UpdateComponent, UpdateCheckResult> checkForUpdates(
- final Collection<UpdateComponent> components) {
- if (channel != UpdateChannel.NIGHTLY) {
- LOG.info("Channel {} is not nightly, aborting", channel);
- return Collections.emptyMap();
- }
- LOG.info("Retrieving latest versions.");
- final List<NightlyResult> resultsList = new Gson().fromJson(getJson(),
- new TypeToken<List<NightlyResult>>(){}.getType());
- if (resultsList == null) {
- return Collections.emptyMap();
- }
- resultsList.stream()
- .filter(Objects::nonNull) //This is incase the JSON is broken
- .forEach(e -> {
- final Matcher matcher = pattern.matcher(e.getName());
- if (matcher.matches()) {
- e.setOtherName(matcher.group(1));
- e.setVersion(new Version(matcher.group(2)));
- e.setUrl(UPDATE_URL + '/' + e.getName());
- }
- });
- final Map<String, NightlyResult> resultsMap = resultsList.stream()
- .collect(Collectors.toMap(NightlyResult::getOtherName, Function.identity()));
- final Map<UpdateComponent, UpdateCheckResult> returns = new HashMap<>();
- components.forEach(e -> {
- if (resultsMap.containsKey(e.getName())) {
- if (resultsMap.get(e.getName()).getVersion().compareTo(e.getVersion()) > 0) {
- final String name = e.getName();
- final NightlyResult result = resultsMap.get(e.getName());
- try {
- returns.put(e, new BaseDownloadableResult(e, getURL(result),
- result.getOtherName(), result.getVersion()));
- } catch (MalformedURLException e1) {
- LOG.error("Unable to create a URL for {}", name);
- }
- LOG.info("Updating {} from {} to {}", e.getName(), e.getVersion(),
- resultsMap.get(e.getName()).getVersion());
- } else {
- LOG.info("Not updating {} from {} to {}", e.getName(), e.getVersion(),
- resultsMap.get(e.getName()).getVersion());
- }
- }
- });
- return returns;
- }
-
- private URL getURL(final NightlyResult result) throws MalformedURLException {
- return new URL(result.getUrl());
- }
-
- private String getJson() {
- try {
- return downloader.getPage(UPDATE_URL).stream().map(String::toString)
- .collect(Collectors.joining("\r\n"));
- } catch (IOException e) {
- LOG.warn("Error when getting update page: {}", e.getMessage());
- return "";
- }
- }
-
- /**
- * Wrapper class for GSON to deserialise the JSON.
- */
- private static class NightlyResult {
- private final String name;
- private final String type;
- private final String mtime;
- private final int size;
- private String otherName;
- private Version version;
- private String url;
-
- NightlyResult(final String name, final String type, final String mtime,
- final int size) {
- this.name = name;
- this.type = type;
- this.mtime = mtime;
- this.size = size;
- }
-
- String getName() {
- return name;
- }
-
- String getUrl() {
- return url;
- }
-
- String getOtherName() {
- return otherName;
- }
-
- void setOtherName(final String otherName) {
- this.otherName = otherName;
- }
-
- Version getVersion() {
- return version;
- }
-
- void setVersion(final Version version) {
- this.version = version;
- }
-
- void setUrl(final String url) {
- this.url = url;
- }
-
- public String toString() {
- return MoreObjects.toStringHelper(NightlyChecker.class)
- .add("name", otherName)
- .add("version", version)
- .toString();
- }
- }
- }
|