Removed old version checker service

This commit is contained in:
yueh
2020-06-07 16:02:14 +02:00
parent 1c7a28c606
commit 61d0781099
26 changed files with 0 additions and 1859 deletions
-12
View File
@@ -42,8 +42,6 @@ import appeng.hooks.TickHandler;
import appeng.parts.PartPlacement;
import appeng.server.AECommand;
import appeng.server.ServerHelper;
import appeng.services.VersionChecker;
import appeng.services.version.VersionCheckerConfig;
import com.google.common.base.Stopwatch;
import net.minecraft.block.Block;
import net.minecraft.entity.EntityType;
@@ -99,8 +97,6 @@ public final class AppEng
//FIXME private final Registration registration;
private VersionCheckerConfig versionCheckerConfig = VersionCheckerConfig.create();
/**
* determined in pre-init but used in init
*/
@@ -164,14 +160,6 @@ public final class AppEng
Registration.setupInternalRegistries();
Registration.postInit();
if( versionCheckerConfig.isVersionCheckingEnabled() )
{
final VersionChecker versionChecker = new VersionChecker( versionCheckerConfig );
final Thread versionCheckerThread = new Thread( versionChecker );
this.startService( "AE2 VersionChecker", versionCheckerThread );
}
registerNetworkHandler();
}
@@ -1,202 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services;
import java.util.Date;
import javax.annotation.Nonnull;
import com.google.common.base.Preconditions;
import net.minecraft.nbt.CompoundNBT;
import appeng.core.AEConfig;
import appeng.core.AELog;
import appeng.core.AppEng;
import appeng.services.version.ModVersionFetcher;
import appeng.services.version.Version;
import appeng.services.version.VersionCheckerConfig;
import appeng.services.version.VersionFetcher;
import appeng.services.version.VersionParser;
import appeng.services.version.github.FormattedRelease;
import appeng.services.version.github.ReleaseFetcher;
import net.minecraftforge.fml.InterModComms;
import net.minecraftforge.fml.ModList;
/**
* Tries to connect to GitHub to retrieve the most current build.
* After comparison with the local version, several path can be chosen.
*
* If the local version is invalid, somebody might have build that version themselves
* or it is run in a developer environment, then nothing needs to be done.
*
* If GitHub can not be reached, then either is GitHub down
* or the connection to GitHub disturbed, then nothing needs to be done,
* since no comparison can be reached
*
* If the version was just recently checked, then no need to poll again.
* Nobody wants to bother to update several times a day.
*
* Config enables to fine-tune when a version is considered newer
*
* If the local version is newer or equal to the GitHub version,
* then no update needs to be posted
*
* Only after all that cases, if the external version is higher than the local,
* use Version Checker Mod and post several information needed for it to update the mod.
*/
// FIXME: VersionChecker doesn't actually exist in 1.15
public final class VersionChecker implements Runnable
{
private static final int SEC_TO_HOUR = 3600;
private static final int MS_TO_SEC = 1000;
private final VersionCheckerConfig config;
public VersionChecker( @Nonnull final VersionCheckerConfig config )
{
Preconditions.checkNotNull( config );
this.config = config;
}
@Override
public void run()
{
try
{
Thread.yield();
// persist the config
this.config.save();
// process data
final long lastCheck = this.config.lastCheck();
final Date now = new Date();
final long nowInMs = now.getTime();
final long intervalInMs = this.config.interval() * SEC_TO_HOUR * MS_TO_SEC;
final long lastAfterInterval = lastCheck + intervalInMs;
this.processInterval( nowInMs, lastAfterInterval );
}
catch( final Exception exception )
{
// Log any unhandled exception to prevent the JVM from reporting them as unhandled.
AELog.debug( exception );
}
AELog.info( "Stopping AE2 VersionChecker" );
}
/**
* checks if enough time since last check has expired
*
* @param nowInMs now in milli seconds
* @param lastAfterInterval last version check including the interval defined in the config
*/
private void processInterval( final long nowInMs, final long lastAfterInterval )
{
if( nowInMs > lastAfterInterval )
{
final String rawModVersion = AEConfig.VERSION;
final VersionParser parser = new VersionParser();
final VersionFetcher modFetcher = new ModVersionFetcher( rawModVersion, parser );
final ReleaseFetcher githubFetcher = new ReleaseFetcher( this.config, parser );
final Version modVersion = modFetcher.get();
final FormattedRelease githubRelease = githubFetcher.get();
this.processVersions( modVersion, githubRelease );
}
else
{
AELog.info( "Last check was just recently." );
}
}
/**
* Checks if the retrieved version is newer as the current mod version.
* Will notify player if config is enabled.
*
* @param modVersion version of mod
* @param githubRelease release retrieved through github
*/
private void processVersions( @Nonnull final Version modVersion, @Nonnull final FormattedRelease githubRelease )
{
final Version githubVersion = githubRelease.version();
final String modFormatted = modVersion.formatted();
final String ghFormatted = githubVersion.formatted();
if( githubVersion.isNewerAs( modVersion ) )
{
final String changelog = githubRelease.changelog();
if( this.config.shouldNotifyPlayer() )
{
AELog.info( "Newer version is available: " + ghFormatted + " (found) > " + modFormatted + " (current)" );
if( this.config.shouldPostChangelog() )
{
AELog.info( "Changelog: " + changelog );
}
}
this.interactWithVersionCheckerMod( modFormatted, ghFormatted, changelog );
}
else
{
AELog.info( "No newer version is available: " + ghFormatted + "(found) < " + modFormatted + " (current)" );
}
}
/**
* Checks if the version checker mod is installed and handles it depending on that information
*
* @param modFormatted mod version formatted as rv2-beta-8
* @param ghFormatted retrieved github version formatted as rv2-beta-8
* @param changelog retrieved github changelog
*/
private void interactWithVersionCheckerMod( @Nonnull final String modFormatted, @Nonnull final String ghFormatted, @Nonnull final String changelog )
{
if( ModList.get().isLoaded( "VersionChecker" ) )
{
final CompoundNBT versionInf = new CompoundNBT();
versionInf.putString("modDisplayName", AppEng.MOD_NAME);
versionInf.putString("oldVersion", modFormatted);
versionInf.putString("newVersion", ghFormatted);
versionInf.putString("updateUrl", "http://ae-mod.info/builds/appliedenergistics2-" + ghFormatted + ".jar");
versionInf.putBoolean("isDirectLink", true);
if( !changelog.isEmpty() )
{
versionInf.putString("changeLog", changelog);
}
versionInf.putString("newFileName", "appliedenergistics2-" + ghFormatted + ".jar");
InterModComms.sendTo( "VersionChecker", "addUpdate", () -> versionInf );
AELog.info( "Reported new version to VersionChecker mod." );
}
else
{
AELog.info( "VersionChecker mod is not installed; Proceeding." );
}
}
}
@@ -1,123 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services.version;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import com.google.common.base.Preconditions;
/**
* Base version of {@link Version}.
*
* Provides a unified way to test for equality and print a formatted string
*/
public abstract class BaseVersion implements Version
{
@Nonnegative
private final int revision;
@Nonnull
private final Channel channel;
@Nonnegative
private final int build;
/**
* @param revision revision in natural number
* @param channel channel
* @param build build in natural number
*
* @throws AssertionError if assertion are enabled and revision or build are not natural numbers
*/
public BaseVersion( @Nonnegative final int revision, @Nonnull final Channel channel, @Nonnegative final int build )
{
Preconditions.checkArgument( revision >= 0 );
Preconditions.checkNotNull( channel );
Preconditions.checkArgument( build >= 0 );
this.revision = revision;
this.channel = channel;
this.build = build;
}
@Override
public final int revision()
{
return this.revision;
}
@Override
public final Channel channel()
{
return this.channel;
}
@Override
public final int build()
{
return this.build;
}
@Override
public String formatted()
{
return "rv" + this.revision + '-' + this.channel.name().toLowerCase() + '-' + this.build;
}
@Override
public final int hashCode()
{
int result = this.revision;
result = 31 * result + this.channel.hashCode();
result = 31 * result + this.build;
return result;
}
@Override
public final boolean equals( final Object o )
{
if( this == o )
{
return true;
}
if( !( o instanceof Version ) )
{
return false;
}
final Version that = (Version) o;
if( this.revision != that.revision() )
{
return false;
}
if( this.build != that.build() )
{
return false;
}
return this.channel == that.channel();
}
@Override
public final String toString()
{
return "Version{" + "revision=" + this.revision + ", channel=" + this.channel + ", build=" + this.build + '}';
}
}
@@ -1,29 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services.version;
/**
* Represents the release channel of Applied Energistics. The mod is either in Alpha, Beta or Stable channel.
* Any more might be confusing to the end-user
*/
public enum Channel
{
Alpha, Beta, Stable
}
@@ -1,51 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services.version;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
/**
* AE prints version like rv2-beta-8
* GitHub prints version like rv2.beta.8
*/
public final class DefaultVersion extends BaseVersion
{
/**
* @param revision natural number
* @param channel either alpha, beta or release
* @param build natural number
*/
public DefaultVersion( @Nonnegative final int revision, @Nonnull final Channel channel, @Nonnegative final int build )
{
super( revision, channel, build );
}
@Override
public boolean isNewerAs( final Version maybeOlder )
{
final boolean isNewerRevision = this.revision() > maybeOlder.revision();
final boolean isNewerChannel = this.channel().compareTo( maybeOlder.channel() ) > 0;
final boolean isNewerBuild = this.build() > maybeOlder.build();
return isNewerRevision || isNewerChannel || isNewerBuild;
}
}
@@ -1,43 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services.version;
/**
* Exceptional template for {@link Version}, when the mod does not want a check
*/
public final class DoNotCheckVersion extends BaseVersion
{
public DoNotCheckVersion()
{
super( Integer.MAX_VALUE, Channel.Stable, Integer.MAX_VALUE );
}
@Override
public boolean isNewerAs( final Version maybeOlder )
{
return true;
}
@Override
public String formatted()
{
return "dev build";
}
}
@@ -1,48 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services.version;
/**
* Exceptional template when the {@link Version} could not be retrieved
*/
public final class MissingVersion extends BaseVersion
{
public MissingVersion()
{
super( 0, Channel.Alpha, 0 );
}
/**
* @param maybeOlder ignored
*
* @return false
*/
@Override
public boolean isNewerAs( final Version maybeOlder )
{
return false;
}
@Override
public String formatted()
{
return "missing";
}
}
@@ -1,75 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services.version;
import javax.annotation.Nonnull;
import appeng.core.AELog;
import appeng.services.version.exceptions.VersionCheckerException;
/**
* Wrapper for {@link VersionParser} to check if the check is happening in developer environment or in a pull request.
*
* In that case ignore the check.
*/
public final class ModVersionFetcher implements VersionFetcher
{
private static final Version EXCEPTIONAL_VERSION = new MissingVersion();
@Nonnull
private final String rawModVersion;
@Nonnull
private final VersionParser parser;
public ModVersionFetcher( @Nonnull final String rawModVersion, @Nonnull final VersionParser parser )
{
this.rawModVersion = rawModVersion;
this.parser = parser;
}
/**
* Parses only, if not checked in developer environment or in a pull request
*
* @return {@link DoNotCheckVersion} if in developer environment or pull request, {@link MissingVersion} in case of
* a parser exception or else the parsed {@link Version}.
*/
@Override
public Version get()
{
if( this.rawModVersion.equals( "@version@" ) || this.rawModVersion.contains( "pr" ) )
{
return new DoNotCheckVersion();
}
try
{
final Version version = this.parser.parse( this.rawModVersion );
return version;
}
catch( final VersionCheckerException e )
{
AELog.debug( e );
return EXCEPTIONAL_VERSION;
}
}
}
@@ -1,60 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services.version;
/**
* Stores version information, which are easily compared
*/
public interface Version
{
/**
* @return revision of this version
*/
int revision();
/**
* @return channel of this version
*/
Channel channel();
/**
* @return build of this version
*/
int build();
/**
* A version is never if these criteria are met:
* if the current revision is higher than the compared revision OR
* if revision are equal and the current channel is higher than the compared channel (Stable > Beta > Alpha) OR
* if revision, channel are equal and the build is higher than the compared build
*
* @return true if criteria are met
*/
boolean isNewerAs( Version maybeOlder );
/**
* Prints the revision, channel and build into a common displayed way
*
* rv2-beta-8
*
* @return formatted version
*/
String formatted();
}
@@ -1,158 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services.version;
import java.util.Date;
import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.common.ForgeConfigSpec.ConfigValue;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.config.ModConfig;
import org.apache.commons.lang3.tuple.Pair;
/**
* Separate config file to handle the version checker
*/
public final class VersionCheckerConfig
{
private static final int DEFAULT_INTERVAL_HOURS = 24;
private static final int MIN_INTERVAL_HOURS = 0;
private static final int MAX_INTERVAL_HOURS = 7 * 24;
private final Config config;
private final ForgeConfigSpec spec;
private VersionCheckerConfig(final Config config, ForgeConfigSpec spec)
{
this.config = config;
this.spec = spec;
}
public boolean isVersionCheckingEnabled()
{
return config.isEnabled.get();
}
public long lastCheck()
{
return config.lastCheck.get();
}
/**
* Stores the current date in milli seconds into the "lastCheck" field of the config and makes it persistent.
*/
public void updateLastCheck()
{
final Date now = new Date();
final long nowInMs = now.getTime();
this.config.lastCheck.set(nowInMs);
}
public int interval()
{
return config.interval.get();
}
public String level()
{
return config.level.get();
}
public boolean shouldNotifyPlayer()
{
return config.shouldNotifyPlayer.get();
}
public boolean shouldPostChangelog()
{
return config.shouldPostChangelog.get();
}
public void save()
{
spec.save();
}
public static VersionCheckerConfig create() {
final Pair<Config, ForgeConfigSpec> specPair = new ForgeConfigSpec.Builder().configure(Config::new);
Config config = specPair.getLeft();
ForgeConfigSpec spec = specPair.getRight();
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, spec);
return new VersionCheckerConfig(config, spec);
}
private static class Config {
final ConfigValue<Boolean> isEnabled;
final ConfigValue<Long> lastCheck;
final ConfigValue<Integer> interval;
final ConfigValue<String> level;
final ForgeConfigSpec.BooleanValue shouldNotifyPlayer;
final ForgeConfigSpec.BooleanValue shouldPostChangelog;
public Config(ForgeConfigSpec.Builder builder) {
// initializes default values by caching
builder.push("general");
this.isEnabled = builder
.comment("If true, the version checker is enabled. Acts as a master switch.")
.define("enabled", true);
builder.pop();
builder.push("cache");
this.lastCheck = builder
.comment("The number of milliseconds since January 1, 1970, 00:00:00 GMT of the last successful check.")
.define("lastCheck", 0L);
this.interval = builder
.comment("Waits as many hours, until it checks again.")
.define( "interval", DEFAULT_INTERVAL_HOURS, val -> {
if (!(val instanceof Integer)) {
return false;
}
int intVal = (Integer) val;
return (intVal >= MIN_INTERVAL_HOURS) && (intVal <= MAX_INTERVAL_HOURS);
});
builder.pop();
builder.push("channel");
this.level = builder.comment("Determines the channel level which should be checked for updates. Can be either Stable, Beta or Alpha.")
.define("level", "Beta");
builder.pop();
builder.push("client");
this.shouldNotifyPlayer = builder.comment("If true, the player is getting a notification, that a new version is available.")
.define("notify", true);
this.shouldPostChangelog = builder.comment("If true, the player is getting a notification including changelog. Only happens if notification are enabled.")
.define("changelog", true);
builder.pop();
}
}
}
@@ -1,28 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services.version;
/**
* Processes base information to retrieve a {@link Version}
*/
public interface VersionFetcher
{
Version get();
}
@@ -1,200 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services.version;
import java.util.Scanner;
import java.util.regex.Pattern;
import javax.annotation.Nonnull;
import com.google.common.base.Preconditions;
import appeng.services.version.exceptions.InvalidBuildException;
import appeng.services.version.exceptions.InvalidChannelException;
import appeng.services.version.exceptions.InvalidRevisionException;
import appeng.services.version.exceptions.InvalidVersionException;
import appeng.services.version.exceptions.MissingSeparatorException;
import appeng.services.version.exceptions.VersionCheckerException;
/**
* can parse a version in form of rv2-beta-8 or rv2.beta.8
*/
public final class VersionParser
{
private static final Pattern PATTERN_DOT = Pattern.compile( "\\." );
private static final Pattern PATTERN_DASH = Pattern.compile( "-" );
private static final Pattern PATTERN_REVISION = Pattern.compile( "[^0-9]+" );
private static final Pattern PATTERN_BUILD = Pattern.compile( "[^0-9]+" );
private static final Pattern PATTERN_NATURAL = Pattern.compile( "[0-9]+" );
private static final Pattern PATTERN_VALID_REVISION = Pattern.compile( "^rv\\d+$" );
/**
* Parses the {@link Version} out of a String
*
* @param raw String in form of rv2-beta-8 or rv2.beta.8
*
* @return {@link Version} encoded in the raw String
*
* @throws VersionCheckerException if parsing the raw string was not successful.
*
*/
public Version parse( @Nonnull final String raw ) throws VersionCheckerException
{
Preconditions.checkNotNull( raw );
final String transformed = this.transformDelimiter( raw );
final String[] split = transformed.split( "_" );
return this.parseVersion( split );
}
/**
* Replaces all "." and "-" into "_" to make them uniform
*
* @param raw raw version string containing "." or "-"
*
* @return transformed raw, where "." and "-" are replaced by "_"
*
* @throws MissingSeparatorException if not containing valid separators
*/
private String transformDelimiter( @Nonnull final String raw ) throws MissingSeparatorException
{
if( !( raw.contains( "." ) || raw.contains( "-" ) ) )
{
throw new MissingSeparatorException();
}
final String withoutDot = PATTERN_DOT.matcher( raw ).replaceAll( "_" );
final String withoutDash = PATTERN_DASH.matcher( withoutDot ).replaceAll( "_" );
return withoutDash;
}
/**
* parses the {@link Version} out of the split.
* The split must have a length of 3,
* representing revision, channel and build.
*
* @param splitRaw raw version split with length of 3
*
* @return {@link Version} represented by the splitRaw
*
* @throws InvalidVersionException when length not 3
* @throws InvalidRevisionException {@link VersionParser#parseRevision(String)}
* @throws InvalidChannelException {@link VersionParser#parseChannel(String)}
* @throws InvalidBuildException {@link VersionParser#parseBuild(String)}
*/
private Version parseVersion( @Nonnull final String[] splitRaw ) throws InvalidVersionException, InvalidRevisionException, InvalidChannelException, InvalidBuildException
{
if( splitRaw.length != 3 )
{
throw new InvalidVersionException();
}
final String rawRevision = splitRaw[0];
final String rawChannel = splitRaw[1];
final String rawBuild = splitRaw[2];
final int revision = this.parseRevision( rawRevision );
final Channel channel = this.parseChannel( rawChannel );
final int build = this.parseBuild( rawBuild );
return new DefaultVersion( revision, channel, build );
}
/**
* A revision starts with the keyword "rv", followed by a natural number
*
* @param rawRevision String containing the revision number
*
* @return revision number
*
* @throws InvalidRevisionException if not matching "rv" followed by a natural number.
*/
private int parseRevision( @Nonnull final String rawRevision ) throws InvalidRevisionException
{
if( !PATTERN_VALID_REVISION.matcher( rawRevision ).matches() )
{
throw new InvalidRevisionException();
}
final Scanner scanner = new Scanner( rawRevision );
final int revision = scanner.useDelimiter( PATTERN_REVISION ).nextInt();
scanner.close();
return revision;
}
/**
* A channel is atm either one of {@link Channel#Alpha}, {@link Channel#Beta} or {@link Channel#Stable}
*
* @param rawChannel String containing the channel
*
* @return matching {@link Channel} to the String
*
* @throws InvalidChannelException if not one of {@link Channel} values.
*/
private Channel parseChannel( @Nonnull final String rawChannel ) throws InvalidChannelException
{
if( !( rawChannel.equalsIgnoreCase( Channel.Alpha.name() ) || rawChannel.equalsIgnoreCase( Channel.Beta.name() ) || rawChannel
.equalsIgnoreCase( Channel.Stable.name() ) ) )
{
throw new InvalidChannelException();
}
for( final Channel channel : Channel.values() )
{
if( channel.name().equalsIgnoreCase( rawChannel ) )
{
return channel;
}
}
throw new InvalidChannelException();
}
/**
* A build is just a natural number
*
* @param rawBuild String containing the build number
*
* @return build number
*
* @throws InvalidBuildException if not a natural number.
*/
private int parseBuild( @Nonnull final String rawBuild ) throws InvalidBuildException
{
if( !PATTERN_NATURAL.matcher( rawBuild ).matches() )
{
throw new InvalidBuildException();
}
final Scanner scanner = new Scanner( rawBuild );
final int build = scanner.useDelimiter( PATTERN_BUILD ).nextInt();
scanner.close();
return build;
}
}
@@ -1,33 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services.version.exceptions;
/**
* Indicates a invalid build number, which is any string except a natural number.
*/
public class InvalidBuildException extends VersionCheckerException
{
private static final long serialVersionUID = 3015432444672364991L;
public InvalidBuildException()
{
super( "Invalid Build: Needs to be a natural number." );
}
}
@@ -1,36 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services.version.exceptions;
import appeng.services.version.Channel;
/**
* Indicates an invalid {@link Channel} value.
*/
public class InvalidChannelException extends VersionCheckerException
{
private static final long serialVersionUID = -1306378515002341620L;
public InvalidChannelException()
{
super( "Invalid Channel: Needs to be one of the following values; alpha, beta, or stable." );
}
}
@@ -1,34 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services.version.exceptions;
/**
* Indicates a invalid revision, which does not match the pattern "rv" followed by a natural number.
*/
public class InvalidRevisionException extends VersionCheckerException
{
private static final long serialVersionUID = 4828906902143875942L;
public InvalidRevisionException()
{
super( "Invalid Revision: Needs to be 'rv' followd by a natural number." );
}
}
@@ -1,34 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services.version.exceptions;
/**
* Indicates an invalid version, which does not consists of 3 parts matching /(rv\d+)-(alpha|beta|stable)-(b\d+)/.
*/
public class InvalidVersionException extends VersionCheckerException
{
private static final long serialVersionUID = 4828906902143875942L;
public InvalidVersionException()
{
super( "Invalid Version Format: Need to consist of exactly 3 parts separated by a dash." );
}
}
@@ -1,35 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services.version.exceptions;
/**
* Indicates a version without a valid separator.
*
* Valid separators are a dash ("-") or dot (".")
*/
public class MissingSeparatorException extends VersionCheckerException
{
private static final long serialVersionUID = 8366370192017020750L;
public MissingSeparatorException()
{
super( "Invalid Revision: Needs to match 'rv' followed by a natural number." );
}
}
@@ -1,36 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services.version.exceptions;
import javax.annotation.Nonnull;
/**
* A super class for any exception thrown by the version checker for easier handling.
*/
public class VersionCheckerException extends Exception
{
private static final long serialVersionUID = 4582501864800542884L;
public VersionCheckerException( @Nonnull final String string )
{
super( string );
}
}
@@ -1,54 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services.version.github;
import javax.annotation.Nonnull;
import appeng.services.version.Version;
/**
* Default template when a {@link FormattedRelease} is needed.
*/
public final class DefaultFormattedRelease implements FormattedRelease
{
@Nonnull
private final Version version;
@Nonnull
private final String changelog;
public DefaultFormattedRelease( @Nonnull final Version version, @Nonnull final String changelog )
{
this.version = version;
this.changelog = changelog;
}
@Override
public String changelog()
{
return this.changelog;
}
@Override
public Version version()
{
return this.version;
}
}
@@ -1,39 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services.version.github;
import appeng.services.version.Version;
/**
* Represents the acquired, processed information through github about a release of Applied Energistics 2
*/
public interface FormattedRelease
{
/**
* @return changelog
*/
String changelog();
/**
* @return processed version
*/
Version version();
}
@@ -1,58 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services.version.github;
import javax.annotation.Nonnull;
import appeng.services.version.MissingVersion;
import appeng.services.version.Version;
/**
* Exceptional template, when no meaningful {@link FormattedRelease} could be obtained
*/
public final class MissingFormattedRelease implements FormattedRelease
{
@Nonnull
private final Version version;
public MissingFormattedRelease()
{
this.version = new MissingVersion();
}
/**
* @return empty string
*/
@Override
public String changelog()
{
return "";
}
/**
* @return {@link MissingVersion}
*/
@Override
public Version version()
{
return this.version;
}
}
@@ -1,37 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services.version.github;
/**
* Template class for Gson to write values from the Json Object into an actual class
*/
@SuppressWarnings( "all" )
public class Release
{
/**
* name of the tag it is saved
*/
public String tag_name;
/**
* Contains the changelog
*/
public String body;
}
@@ -1,122 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services.version.github;
import java.io.IOException;
import java.lang.reflect.Type;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import javax.annotation.Nonnull;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.apache.commons.io.IOUtils;
import appeng.core.AELog;
import appeng.services.version.Channel;
import appeng.services.version.Version;
import appeng.services.version.VersionCheckerConfig;
import appeng.services.version.VersionParser;
import appeng.services.version.exceptions.VersionCheckerException;
public final class ReleaseFetcher
{
private static final String GITHUB_RELEASES_URL = "https://api.github.com/repos/AppliedEnergistics/Applied-Energistics-2/releases";
private static final FormattedRelease EXCEPTIONAL_RELEASE = new MissingFormattedRelease();
@Nonnull
private final VersionCheckerConfig config;
@Nonnull
private final VersionParser parser;
public ReleaseFetcher( @Nonnull final VersionCheckerConfig config, @Nonnull final VersionParser parser )
{
this.config = config;
this.parser = parser;
}
public FormattedRelease get()
{
final Gson gson = new Gson();
final Type type = new ReleasesTypeToken().getType();
try
{
final URL releasesURL = new URL( GITHUB_RELEASES_URL );
final String rawReleases = this.getRawReleases( releasesURL );
this.config.updateLastCheck();
final List<Release> releases = gson.fromJson( rawReleases, type );
final FormattedRelease latestFitRelease = this.getLatestFitRelease( releases );
return latestFitRelease;
}
catch( final VersionCheckerException e )
{
AELog.debug( e );
}
catch( final MalformedURLException e )
{
AELog.debug( e );
}
catch( final IOException e )
{
AELog.debug( e );
}
return EXCEPTIONAL_RELEASE;
}
private String getRawReleases( final URL url ) throws IOException
{
return IOUtils.toString( url );
}
private FormattedRelease getLatestFitRelease( final Iterable<Release> releases ) throws VersionCheckerException
{
final String levelInConfig = this.config.level();
final Channel level = Channel.valueOf( levelInConfig );
final int levelOrdinal = level.ordinal();
for( final Release release : releases )
{
final String rawVersion = release.tag_name;
final String changelog = release.body;
final Version version = this.parser.parse( rawVersion );
if( version.channel().ordinal() >= levelOrdinal )
{
return new DefaultFormattedRelease( version, changelog );
}
}
return EXCEPTIONAL_RELEASE;
}
private static final class ReleasesTypeToken extends TypeToken<List<Release>>
{
}
}