From 47592bcbcb39fc45b51154525e02acfc1246cdfe Mon Sep 17 00:00:00 2001 From: yueh Date: Mon, 5 Oct 2015 16:10:44 +0200 Subject: [PATCH] Fixes #1932: Better VersionChecker exception handling ModVersionFetcher will now return a MissingVersion in case of an exception instead of letting it propagate upwards. Also added a generic try/catch to the VersionChecker itself, just in case any unchecked exception might be triggered inside the thread and at least not logged correctly. --- .../java/appeng/services/VersionChecker.java | 44 ++++++++---- .../appeng/services/version/BaseVersion.java | 35 ++++++++-- .../services/version/DefaultVersion.java | 23 ++++++- .../services/version/MissingVersion.java | 17 +++++ .../services/version/ModVersionFetcher.java | 41 ++++++++++- .../version/VersionCheckerConfig.java | 12 +++- .../services/version/VersionFetcher.java | 17 +++++ .../services/version/VersionParser.java | 68 +++++++++++++++---- .../exceptions/InvalidBuildException.java | 33 +++++++++ .../exceptions/InvalidChannelException.java | 36 ++++++++++ .../exceptions/InvalidRevisionException.java | 34 ++++++++++ .../exceptions/InvalidVersionException.java | 34 ++++++++++ .../exceptions/MissingSeparatorException.java | 35 ++++++++++ .../exceptions/VersionCheckerException.java | 36 ++++++++++ .../github/DefaultFormattedRelease.java | 23 ++++++- .../version/github/FormattedRelease.java | 17 +++++ .../github/MissingFormattedRelease.java | 20 ++++++ .../services/version/github/Release.java | 17 +++++ .../version/github/ReleaseFetcher.java | 41 +++++++++-- .../services/version/VersionParserTest.java | 52 ++++++++++---- 20 files changed, 577 insertions(+), 58 deletions(-) create mode 100644 src/main/java/appeng/services/version/exceptions/InvalidBuildException.java create mode 100644 src/main/java/appeng/services/version/exceptions/InvalidChannelException.java create mode 100644 src/main/java/appeng/services/version/exceptions/InvalidRevisionException.java create mode 100644 src/main/java/appeng/services/version/exceptions/InvalidVersionException.java create mode 100644 src/main/java/appeng/services/version/exceptions/MissingSeparatorException.java create mode 100644 src/main/java/appeng/services/version/exceptions/VersionCheckerException.java diff --git a/src/main/java/appeng/services/VersionChecker.java b/src/main/java/appeng/services/VersionChecker.java index 8af91c1c..11d698f6 100644 --- a/src/main/java/appeng/services/VersionChecker.java +++ b/src/main/java/appeng/services/VersionChecker.java @@ -21,6 +21,10 @@ package appeng.services; import java.util.Date; +import javax.annotation.Nonnull; + +import com.google.common.base.Preconditions; + import net.minecraft.nbt.NBTTagCompound; import cpw.mods.fml.common.Loader; @@ -66,30 +70,40 @@ public final class VersionChecker implements Runnable private static final int MS_TO_SEC = 1000; private final VersionCheckerConfig config; - public VersionChecker( final VersionCheckerConfig config ) + public VersionChecker( @Nonnull final VersionCheckerConfig config ) { + Preconditions.checkNotNull( config ); + this.config = config; } @Override public void run() { - Thread.yield(); + try + { + Thread.yield(); - // persist the config - this.config.save(); + // persist the config + this.config.save(); - // retrieve data - final String rawLastCheck = this.config.lastCheck(); + // retrieve data + final String rawLastCheck = this.config.lastCheck(); - // process data - final long lastCheck = Long.parseLong( rawLastCheck ); - 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; + // process data + final long lastCheck = Long.parseLong( rawLastCheck ); + 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 ); + this.processInterval( nowInMs, lastAfterInterval ); + } + catch( Exception exception ) + { + // Log any unhandled exception to prevent the JVM from reporting them as unhandled. + AELog.error( exception ); + } AELog.info( "Stopping AE2 VersionChecker" ); } @@ -127,7 +141,7 @@ public final class VersionChecker implements Runnable * @param modVersion version of mod * @param githubRelease release retrieved through github */ - private void processVersions( final Version modVersion, final FormattedRelease githubRelease ) + private void processVersions( @Nonnull final Version modVersion, @Nonnull final FormattedRelease githubRelease ) { final Version githubVersion = githubRelease.version(); final String modFormatted = modVersion.formatted(); @@ -162,7 +176,7 @@ public final class VersionChecker implements Runnable * @param ghFormatted retrieved github version formatted as rv2-beta-8 * @param changelog retrieved github changelog */ - private void interactWithVersionCheckerMod( final String modFormatted, final String ghFormatted, final String changelog ) + private void interactWithVersionCheckerMod( @Nonnull final String modFormatted, @Nonnull final String ghFormatted, @Nonnull final String changelog ) { if( Loader.isModLoaded( "VersionChecker" ) ) { diff --git a/src/main/java/appeng/services/version/BaseVersion.java b/src/main/java/appeng/services/version/BaseVersion.java index 0102e1c1..d998a868 100644 --- a/src/main/java/appeng/services/version/BaseVersion.java +++ b/src/main/java/appeng/services/version/BaseVersion.java @@ -1,7 +1,30 @@ +/* + * 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 . + */ package appeng.services.version; +import javax.annotation.Nonnegative; +import javax.annotation.Nonnull; + +import com.google.common.base.Preconditions; + + /** * Base version of {@link Version}. * @@ -9,8 +32,11 @@ package appeng.services.version; */ public abstract class BaseVersion implements Version { + @Nonnegative private final int revision; + @Nonnull private final Channel channel; + @Nonnegative private final int build; /** @@ -20,10 +46,11 @@ public abstract class BaseVersion implements Version * * @throws AssertionError if assertion are enabled and revision or build are not natural numbers */ - public BaseVersion( final int revision, final Channel channel, final int build ) + public BaseVersion( @Nonnegative final int revision, @Nonnull final Channel channel, @Nonnegative final int build ) { - assert revision >= 0; - assert build >= 0; + Preconditions.checkArgument( revision >= 0 ); + Preconditions.checkNotNull( channel ); + Preconditions.checkArgument( build >= 0 ); this.revision = revision; this.channel = channel; @@ -58,7 +85,7 @@ public abstract class BaseVersion implements Version public final int hashCode() { int result = this.revision; - result = 31 * result + ( this.channel != null ? this.channel.hashCode() : 0 ); + result = 31 * result + this.channel.hashCode(); result = 31 * result + this.build; return result; } diff --git a/src/main/java/appeng/services/version/DefaultVersion.java b/src/main/java/appeng/services/version/DefaultVersion.java index 2bcb834b..1f8f8e77 100644 --- a/src/main/java/appeng/services/version/DefaultVersion.java +++ b/src/main/java/appeng/services/version/DefaultVersion.java @@ -1,7 +1,28 @@ +/* + * 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 . + */ 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 @@ -13,7 +34,7 @@ public final class DefaultVersion extends BaseVersion * @param channel either alpha, beta or release * @param build natural number */ - public DefaultVersion( final int revision, final Channel channel, final int build ) + public DefaultVersion( @Nonnegative final int revision, @Nonnull final Channel channel, @Nonnegative final int build ) { super( revision, channel, build ); } diff --git a/src/main/java/appeng/services/version/MissingVersion.java b/src/main/java/appeng/services/version/MissingVersion.java index 6ff01351..4928aeb6 100644 --- a/src/main/java/appeng/services/version/MissingVersion.java +++ b/src/main/java/appeng/services/version/MissingVersion.java @@ -1,3 +1,20 @@ +/* + * 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 . + */ package appeng.services.version; diff --git a/src/main/java/appeng/services/version/ModVersionFetcher.java b/src/main/java/appeng/services/version/ModVersionFetcher.java index 1c6ac5e4..6a4c5b1f 100644 --- a/src/main/java/appeng/services/version/ModVersionFetcher.java +++ b/src/main/java/appeng/services/version/ModVersionFetcher.java @@ -1,7 +1,30 @@ +/* + * 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 . + */ 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. * @@ -9,10 +32,14 @@ package appeng.services.version; */ 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( final String rawModVersion, final VersionParser parser ) + public ModVersionFetcher( @Nonnull final String rawModVersion, @Nonnull final VersionParser parser ) { this.rawModVersion = rawModVersion; this.parser = parser; @@ -21,7 +48,8 @@ public final class ModVersionFetcher implements VersionFetcher /** * Parses only, if not checked in developer environment or in a pull request * - * @return {@link DoNotCheckVersion} if in developer environment or pull request, else the parsed {@link Version} + * @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() @@ -30,11 +58,18 @@ public final class ModVersionFetcher implements VersionFetcher { return new DoNotCheckVersion(); } - else + + try { final Version version = this.parser.parse( this.rawModVersion ); return version; } + catch( final VersionCheckerException e ) + { + AELog.error( e ); + + return EXCEPTIONAL_VERSION; + } } } diff --git a/src/main/java/appeng/services/version/VersionCheckerConfig.java b/src/main/java/appeng/services/version/VersionCheckerConfig.java index d69859ff..0dbb9427 100644 --- a/src/main/java/appeng/services/version/VersionCheckerConfig.java +++ b/src/main/java/appeng/services/version/VersionCheckerConfig.java @@ -22,6 +22,10 @@ package appeng.services.version; import java.io.File; import java.util.Date; +import javax.annotation.Nonnull; + +import com.google.common.base.Preconditions; + import net.minecraftforge.common.config.Configuration; @@ -34,13 +38,16 @@ public final class VersionCheckerConfig private static final int MIN_INTERVAL_HOURS = 0; private static final int MAX_INTERVAL_HOURS = 7 * 24; + @Nonnull private final Configuration config; private final boolean isEnabled; + @Nonnull private final String lastCheck; private final int interval; + @Nonnull private final String level; private final boolean shouldNotifyPlayer; @@ -49,8 +56,11 @@ public final class VersionCheckerConfig /** * @param file requires fully qualified file in which the config is saved */ - public VersionCheckerConfig( final File file ) + public VersionCheckerConfig( @Nonnull final File file ) { + Preconditions.checkNotNull( file ); + Preconditions.checkState( file.isFile() ); + this.config = new Configuration( file ); // initializes default values by caching diff --git a/src/main/java/appeng/services/version/VersionFetcher.java b/src/main/java/appeng/services/version/VersionFetcher.java index 7eb7e6a2..c30faddf 100644 --- a/src/main/java/appeng/services/version/VersionFetcher.java +++ b/src/main/java/appeng/services/version/VersionFetcher.java @@ -1,3 +1,20 @@ +/* + * 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 . + */ package appeng.services.version; diff --git a/src/main/java/appeng/services/version/VersionParser.java b/src/main/java/appeng/services/version/VersionParser.java index 5a2460bd..d256f259 100644 --- a/src/main/java/appeng/services/version/VersionParser.java +++ b/src/main/java/appeng/services/version/VersionParser.java @@ -22,6 +22,17 @@ 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 @@ -42,10 +53,13 @@ public final class VersionParser * * @return {@link Version} encoded in the raw String * - * @throws AssertionError if raw String does not match pattern of a {@link Version} + * @throws VersionCheckerException if parsing the raw string was not successful. + * */ - public Version parse( final String raw ) + public Version parse( @Nonnull final String raw ) throws VersionCheckerException { + Preconditions.checkNotNull( raw ); + final String transformed = this.transformDelimiter( raw ); final String[] split = transformed.split( "_" ); @@ -58,10 +72,15 @@ public final class VersionParser * @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( final String raw ) + private String transformDelimiter( @Nonnull final String raw ) throws MissingSeparatorException { - assert raw.contains( "." ) || raw.contains( "-" ); + if( !( raw.contains( "." ) || raw.contains( "-" ) ) ) + { + throw new MissingSeparatorException(); + } final String withoutDot = PATTERN_DOT.matcher( raw ).replaceAll( "_" ); final String withoutDash = PATTERN_DASH.matcher( withoutDot ).replaceAll( "_" ); @@ -77,10 +96,18 @@ public final class VersionParser * @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( final String[] splitRaw ) + private Version parseVersion( @Nonnull final String[] splitRaw ) throws InvalidVersionException, InvalidRevisionException, InvalidChannelException, InvalidBuildException { - assert splitRaw.length == 3; + if( splitRaw.length != 3 ) + { + throw new InvalidVersionException(); + } final String rawRevision = splitRaw[0]; final String rawChannel = splitRaw[1]; @@ -99,10 +126,15 @@ public final class VersionParser * @param rawRevision String containing the revision number * * @return revision number + * + * @throws InvalidRevisionException if not matching "rv" followed by a natural number. */ - private int parseRevision( final String rawRevision ) + private int parseRevision( @Nonnull final String rawRevision ) throws InvalidRevisionException { - assert PATTERN_VALID_REVISION.matcher( rawRevision ).matches(); + if( !PATTERN_VALID_REVISION.matcher( rawRevision ).matches() ) + { + throw new InvalidRevisionException(); + } final Scanner scanner = new Scanner( rawRevision ); @@ -119,10 +151,15 @@ public final class VersionParser * @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( final String rawChannel ) + private Channel parseChannel( @Nonnull final String rawChannel ) throws InvalidChannelException { - assert rawChannel.equalsIgnoreCase( Channel.Alpha.name() ) || rawChannel.equalsIgnoreCase( Channel.Beta.name() ) || rawChannel.equalsIgnoreCase( Channel.Stable.name() ); + 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() ) { @@ -132,7 +169,7 @@ public final class VersionParser } } - throw new IllegalArgumentException( "Raw channel " + rawChannel + " did not contain any of the pre-programmed types." ); + throw new InvalidChannelException(); } /** @@ -141,10 +178,15 @@ public final class VersionParser * @param rawBuild String containing the build number * * @return build number + * + * @throws InvalidBuildException if not a natural number. */ - private int parseBuild( final String rawBuild ) + private int parseBuild( @Nonnull final String rawBuild ) throws InvalidBuildException { - assert PATTERN_NATURAL.matcher( rawBuild ).matches(); + if( !PATTERN_NATURAL.matcher( rawBuild ).matches() ) + { + throw new InvalidBuildException(); + } final Scanner scanner = new Scanner( rawBuild ); diff --git a/src/main/java/appeng/services/version/exceptions/InvalidBuildException.java b/src/main/java/appeng/services/version/exceptions/InvalidBuildException.java new file mode 100644 index 00000000..b7049016 --- /dev/null +++ b/src/main/java/appeng/services/version/exceptions/InvalidBuildException.java @@ -0,0 +1,33 @@ +/* + * 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 . + */ + +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." ); + } +} diff --git a/src/main/java/appeng/services/version/exceptions/InvalidChannelException.java b/src/main/java/appeng/services/version/exceptions/InvalidChannelException.java new file mode 100644 index 00000000..824d1f87 --- /dev/null +++ b/src/main/java/appeng/services/version/exceptions/InvalidChannelException.java @@ -0,0 +1,36 @@ +/* + * 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 . + */ + +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." ); + } +} diff --git a/src/main/java/appeng/services/version/exceptions/InvalidRevisionException.java b/src/main/java/appeng/services/version/exceptions/InvalidRevisionException.java new file mode 100644 index 00000000..02a155ce --- /dev/null +++ b/src/main/java/appeng/services/version/exceptions/InvalidRevisionException.java @@ -0,0 +1,34 @@ +/* + * 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 . + */ + +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." ); + } +} diff --git a/src/main/java/appeng/services/version/exceptions/InvalidVersionException.java b/src/main/java/appeng/services/version/exceptions/InvalidVersionException.java new file mode 100644 index 00000000..1985bc76 --- /dev/null +++ b/src/main/java/appeng/services/version/exceptions/InvalidVersionException.java @@ -0,0 +1,34 @@ +/* + * 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 . + */ + +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." ); + } +} diff --git a/src/main/java/appeng/services/version/exceptions/MissingSeparatorException.java b/src/main/java/appeng/services/version/exceptions/MissingSeparatorException.java new file mode 100644 index 00000000..f3fc4b35 --- /dev/null +++ b/src/main/java/appeng/services/version/exceptions/MissingSeparatorException.java @@ -0,0 +1,35 @@ +/* + * 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 . + */ + +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." ); + } +} diff --git a/src/main/java/appeng/services/version/exceptions/VersionCheckerException.java b/src/main/java/appeng/services/version/exceptions/VersionCheckerException.java new file mode 100644 index 00000000..caf373b7 --- /dev/null +++ b/src/main/java/appeng/services/version/exceptions/VersionCheckerException.java @@ -0,0 +1,36 @@ +/* + * 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 . + */ + +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 String string ) + { + super( string ); + } +} diff --git a/src/main/java/appeng/services/version/github/DefaultFormattedRelease.java b/src/main/java/appeng/services/version/github/DefaultFormattedRelease.java index 490fa569..c194a296 100644 --- a/src/main/java/appeng/services/version/github/DefaultFormattedRelease.java +++ b/src/main/java/appeng/services/version/github/DefaultFormattedRelease.java @@ -1,7 +1,26 @@ +/* + * 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 . + */ package appeng.services.version.github; +import javax.annotation.Nonnull; + import appeng.services.version.Version; @@ -10,10 +29,12 @@ import appeng.services.version.Version; */ public final class DefaultFormattedRelease implements FormattedRelease { + @Nonnull private final Version version; + @Nonnull private final String changelog; - public DefaultFormattedRelease( final Version version, final String changelog ) + public DefaultFormattedRelease( @Nonnull final Version version, @Nonnull final String changelog ) { this.version = version; this.changelog = changelog; diff --git a/src/main/java/appeng/services/version/github/FormattedRelease.java b/src/main/java/appeng/services/version/github/FormattedRelease.java index 31c75e9b..fef5ae2f 100644 --- a/src/main/java/appeng/services/version/github/FormattedRelease.java +++ b/src/main/java/appeng/services/version/github/FormattedRelease.java @@ -1,3 +1,20 @@ +/* + * 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 . + */ package appeng.services.version.github; diff --git a/src/main/java/appeng/services/version/github/MissingFormattedRelease.java b/src/main/java/appeng/services/version/github/MissingFormattedRelease.java index 318a7338..cbe836cd 100644 --- a/src/main/java/appeng/services/version/github/MissingFormattedRelease.java +++ b/src/main/java/appeng/services/version/github/MissingFormattedRelease.java @@ -1,7 +1,26 @@ +/* + * 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 . + */ package appeng.services.version.github; +import javax.annotation.Nonnull; + import appeng.services.version.MissingVersion; import appeng.services.version.Version; @@ -11,6 +30,7 @@ import appeng.services.version.Version; */ public final class MissingFormattedRelease implements FormattedRelease { + @Nonnull private final Version version; public MissingFormattedRelease() diff --git a/src/main/java/appeng/services/version/github/Release.java b/src/main/java/appeng/services/version/github/Release.java index dec7ec5e..9dc0f651 100644 --- a/src/main/java/appeng/services/version/github/Release.java +++ b/src/main/java/appeng/services/version/github/Release.java @@ -1,3 +1,20 @@ +/* + * 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 . + */ package appeng.services.version.github; diff --git a/src/main/java/appeng/services/version/github/ReleaseFetcher.java b/src/main/java/appeng/services/version/github/ReleaseFetcher.java index 53a91bb5..c63b0960 100644 --- a/src/main/java/appeng/services/version/github/ReleaseFetcher.java +++ b/src/main/java/appeng/services/version/github/ReleaseFetcher.java @@ -1,12 +1,32 @@ +/* + * 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 . + */ 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; @@ -17,6 +37,7 @@ 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 @@ -24,10 +45,12 @@ 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( final VersionCheckerConfig config, final VersionParser parser ) + public ReleaseFetcher( @Nonnull final VersionCheckerConfig config, @Nonnull final VersionParser parser ) { this.config = config; this.parser = parser; @@ -50,12 +73,20 @@ public final class ReleaseFetcher return latestFitRelease; } - catch( final Exception e ) + catch( final VersionCheckerException e ) { AELog.error( e ); - - return EXCEPTIONAL_RELEASE; } + catch( MalformedURLException e ) + { + AELog.error( e ); + } + catch( IOException e ) + { + AELog.error( e ); + } + + return EXCEPTIONAL_RELEASE; } private String getRawReleases( final URL url ) throws IOException @@ -63,7 +94,7 @@ public final class ReleaseFetcher return IOUtils.toString( url ); } - private FormattedRelease getLatestFitRelease( final Iterable releases ) + private FormattedRelease getLatestFitRelease( final Iterable releases ) throws VersionCheckerException { final String levelInConfig = this.config.level(); final Channel level = Channel.valueOf( levelInConfig ); diff --git a/src/test/java/appeng/services/version/VersionParserTest.java b/src/test/java/appeng/services/version/VersionParserTest.java index e45a46dc..59e9138e 100644 --- a/src/test/java/appeng/services/version/VersionParserTest.java +++ b/src/test/java/appeng/services/version/VersionParserTest.java @@ -1,8 +1,16 @@ + package appeng.services.version; import org.junit.Test; +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; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -21,6 +29,8 @@ public final class VersionParserTest private static final String MOD_INVALID_REVISION = "2-beta-8"; private static final String MOD_INVALID_CHANNEL = "rv2-gamma-8"; private static final String MOD_INVALID_BUILD = "rv2-beta-b8"; + private static final String GENERIC_MISSING_SEPARATOR = "foobar"; + private static final String GENERIC_INVALID_VERSION = "foo-bar"; private static final DefaultVersion VERSION = new DefaultVersion( 2, Channel.Beta, 8 ); @@ -32,7 +42,7 @@ public final class VersionParserTest } @Test - public void testSameParsedGitHub() + public void testSameParsedGitHub() throws VersionCheckerException { final Version version = this.parser.parse( GITHUB_VERSION ); @@ -40,50 +50,62 @@ public final class VersionParserTest } @Test - public void testParseGitHub() + public void testParseGitHub() throws VersionCheckerException { assertTrue( this.parser.parse( GITHUB_VERSION ).equals( VERSION ) ); } - @Test( expected = AssertionError.class ) - public void parseGH_InvalidRevision() + @Test( expected = InvalidRevisionException.class ) + public void parseGH_InvalidRevision() throws VersionCheckerException { assertFalse( this.parser.parse( GITHUB_INVALID_REVISION ).equals( VERSION ) ); } - @Test( expected = AssertionError.class ) - public void parseGH_InvalidChannel() + @Test( expected = InvalidChannelException.class ) + public void parseGH_InvalidChannel() throws VersionCheckerException { assertFalse( this.parser.parse( GITHUB_INVALID_CHANNEL ).equals( VERSION ) ); } - @Test( expected = AssertionError.class ) - public void parseGH_InvalidBuild() + @Test( expected = InvalidBuildException.class ) + public void parseGH_InvalidBuild() throws VersionCheckerException { assertFalse( this.parser.parse( GITHUB_INVALID_BUILD ).equals( VERSION ) ); } @Test - public void testParseMod() + public void testParseMod() throws VersionCheckerException { assertTrue( this.parser.parse( MOD_VERSION ).equals( VERSION ) ); } - @Test( expected = AssertionError.class ) - public void parseMod_InvalidRevision() + @Test( expected = InvalidRevisionException.class ) + public void parseMod_InvalidRevision() throws VersionCheckerException { assertFalse( this.parser.parse( MOD_INVALID_REVISION ).equals( VERSION ) ); } - @Test( expected = AssertionError.class ) - public void parseMod_InvalidChannel() + @Test( expected = InvalidChannelException.class ) + public void parseMod_InvalidChannel() throws VersionCheckerException { assertFalse( this.parser.parse( MOD_INVALID_CHANNEL ).equals( VERSION ) ); } - @Test( expected = AssertionError.class ) - public void parseMod_InvalidBuild() + @Test( expected = InvalidBuildException.class ) + public void parseMod_InvalidBuild() throws VersionCheckerException { assertFalse( this.parser.parse( MOD_INVALID_BUILD ).equals( VERSION ) ); } + + @Test( expected = MissingSeparatorException.class ) + public void parseGeneric_MissingSeparator() throws VersionCheckerException + { + assertFalse( this.parser.parse( GENERIC_MISSING_SEPARATOR ).equals( VERSION ) ); + } + + @Test( expected = InvalidVersionException.class ) + public void parseGeneric_InvalidVersion() throws VersionCheckerException + { + assertFalse( this.parser.parse( GENERIC_INVALID_VERSION ).equals( VERSION ) ); + } }