Merge pull request #1934 from yueh/fix-1932

Fixes #1932: Better VersionChecker exception handling
This commit is contained in:
yueh 2015-10-21 14:06:54 +02:00
commit 8f1d22b863
20 changed files with 577 additions and 58 deletions

View file

@ -21,6 +21,10 @@ package appeng.services;
import java.util.Date; import java.util.Date;
import javax.annotation.Nonnull;
import com.google.common.base.Preconditions;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
import cpw.mods.fml.common.Loader; 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 static final int MS_TO_SEC = 1000;
private final VersionCheckerConfig config; private final VersionCheckerConfig config;
public VersionChecker( final VersionCheckerConfig config ) public VersionChecker( @Nonnull final VersionCheckerConfig config )
{ {
Preconditions.checkNotNull( config );
this.config = config; this.config = config;
} }
@Override @Override
public void run() public void run()
{ {
Thread.yield(); try
{
Thread.yield();
// persist the config // persist the config
this.config.save(); this.config.save();
// retrieve data // retrieve data
final String rawLastCheck = this.config.lastCheck(); final String rawLastCheck = this.config.lastCheck();
// process data // process data
final long lastCheck = Long.parseLong( rawLastCheck ); final long lastCheck = Long.parseLong( rawLastCheck );
final Date now = new Date(); final Date now = new Date();
final long nowInMs = now.getTime(); final long nowInMs = now.getTime();
final long intervalInMs = this.config.interval() * SEC_TO_HOUR * MS_TO_SEC; final long intervalInMs = this.config.interval() * SEC_TO_HOUR * MS_TO_SEC;
final long lastAfterInterval = lastCheck + intervalInMs; 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" ); AELog.info( "Stopping AE2 VersionChecker" );
} }
@ -127,7 +141,7 @@ public final class VersionChecker implements Runnable
* @param modVersion version of mod * @param modVersion version of mod
* @param githubRelease release retrieved through github * @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 Version githubVersion = githubRelease.version();
final String modFormatted = modVersion.formatted(); 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 ghFormatted retrieved github version formatted as rv2-beta-8
* @param changelog retrieved github changelog * @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" ) ) if( Loader.isModLoaded( "VersionChecker" ) )
{ {

View file

@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services.version; package appeng.services.version;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import com.google.common.base.Preconditions;
/** /**
* Base version of {@link Version}. * Base version of {@link Version}.
* *
@ -9,8 +32,11 @@ package appeng.services.version;
*/ */
public abstract class BaseVersion implements Version public abstract class BaseVersion implements Version
{ {
@Nonnegative
private final int revision; private final int revision;
@Nonnull
private final Channel channel; private final Channel channel;
@Nonnegative
private final int build; 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 * @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; Preconditions.checkArgument( revision >= 0 );
assert build >= 0; Preconditions.checkNotNull( channel );
Preconditions.checkArgument( build >= 0 );
this.revision = revision; this.revision = revision;
this.channel = channel; this.channel = channel;
@ -58,7 +85,7 @@ public abstract class BaseVersion implements Version
public final int hashCode() public final int hashCode()
{ {
int result = this.revision; 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; result = 31 * result + this.build;
return result; return result;
} }

View file

@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services.version; package appeng.services.version;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
/** /**
* AE prints version like rv2-beta-8 * AE prints version like rv2-beta-8
* GitHub 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 channel either alpha, beta or release
* @param build natural number * @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 ); super( revision, channel, build );
} }

View file

@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services.version; package appeng.services.version;

View file

@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services.version; 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. * 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 public final class ModVersionFetcher implements VersionFetcher
{ {
private static final Version EXCEPTIONAL_VERSION = new MissingVersion();
@Nonnull
private final String rawModVersion; private final String rawModVersion;
@Nonnull
private final VersionParser parser; 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.rawModVersion = rawModVersion;
this.parser = parser; 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 * 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 @Override
public Version get() public Version get()
@ -30,11 +58,18 @@ public final class ModVersionFetcher implements VersionFetcher
{ {
return new DoNotCheckVersion(); return new DoNotCheckVersion();
} }
else
try
{ {
final Version version = this.parser.parse( this.rawModVersion ); final Version version = this.parser.parse( this.rawModVersion );
return version; return version;
} }
catch( final VersionCheckerException e )
{
AELog.error( e );
return EXCEPTIONAL_VERSION;
}
} }
} }

View file

@ -22,6 +22,10 @@ package appeng.services.version;
import java.io.File; import java.io.File;
import java.util.Date; import java.util.Date;
import javax.annotation.Nonnull;
import com.google.common.base.Preconditions;
import net.minecraftforge.common.config.Configuration; 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 MIN_INTERVAL_HOURS = 0;
private static final int MAX_INTERVAL_HOURS = 7 * 24; private static final int MAX_INTERVAL_HOURS = 7 * 24;
@Nonnull
private final Configuration config; private final Configuration config;
private final boolean isEnabled; private final boolean isEnabled;
@Nonnull
private final String lastCheck; private final String lastCheck;
private final int interval; private final int interval;
@Nonnull
private final String level; private final String level;
private final boolean shouldNotifyPlayer; private final boolean shouldNotifyPlayer;
@ -49,8 +56,11 @@ public final class VersionCheckerConfig
/** /**
* @param file requires fully qualified file in which the config is saved * @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 ); this.config = new Configuration( file );
// initializes default values by caching // initializes default values by caching

View file

@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services.version; package appeng.services.version;

View file

@ -22,6 +22,17 @@ package appeng.services.version;
import java.util.Scanner; import java.util.Scanner;
import java.util.regex.Pattern; 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 * 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 * @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 transformed = this.transformDelimiter( raw );
final String[] split = transformed.split( "_" ); final String[] split = transformed.split( "_" );
@ -58,10 +72,15 @@ public final class VersionParser
* @param raw raw version string containing "." or "-" * @param raw raw version string containing "." or "-"
* *
* @return transformed raw, where "." and "-" are replaced by "_" * @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 withoutDot = PATTERN_DOT.matcher( raw ).replaceAll( "_" );
final String withoutDash = PATTERN_DASH.matcher( withoutDot ).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 * @param splitRaw raw version split with length of 3
* *
* @return {@link Version} represented by the splitRaw * @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 rawRevision = splitRaw[0];
final String rawChannel = splitRaw[1]; final String rawChannel = splitRaw[1];
@ -99,10 +126,15 @@ public final class VersionParser
* @param rawRevision String containing the revision number * @param rawRevision String containing the revision number
* *
* @return 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 ); final Scanner scanner = new Scanner( rawRevision );
@ -119,10 +151,15 @@ public final class VersionParser
* @param rawChannel String containing the channel * @param rawChannel String containing the channel
* *
* @return matching {@link Channel} to the String * @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() ) 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 * @param rawBuild String containing the build number
* *
* @return 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 ); final Scanner scanner = new Scanner( rawBuild );

View file

@ -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 <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." );
}
}

View file

@ -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 <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." );
}
}

View file

@ -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 <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." );
}
}

View file

@ -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 <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." );
}
}

View file

@ -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 <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." );
}
}

View file

@ -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 <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 String string )
{
super( string );
}
}

View file

@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services.version.github; package appeng.services.version.github;
import javax.annotation.Nonnull;
import appeng.services.version.Version; import appeng.services.version.Version;
@ -10,10 +29,12 @@ import appeng.services.version.Version;
*/ */
public final class DefaultFormattedRelease implements FormattedRelease public final class DefaultFormattedRelease implements FormattedRelease
{ {
@Nonnull
private final Version version; private final Version version;
@Nonnull
private final String changelog; 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.version = version;
this.changelog = changelog; this.changelog = changelog;

View file

@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services.version.github; package appeng.services.version.github;

View file

@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services.version.github; package appeng.services.version.github;
import javax.annotation.Nonnull;
import appeng.services.version.MissingVersion; import appeng.services.version.MissingVersion;
import appeng.services.version.Version; import appeng.services.version.Version;
@ -11,6 +30,7 @@ import appeng.services.version.Version;
*/ */
public final class MissingFormattedRelease implements FormattedRelease public final class MissingFormattedRelease implements FormattedRelease
{ {
@Nonnull
private final Version version; private final Version version;
public MissingFormattedRelease() public MissingFormattedRelease()

View file

@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services.version.github; package appeng.services.version.github;

View file

@ -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 <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.services.version.github; package appeng.services.version.github;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.List; import java.util.List;
import javax.annotation.Nonnull;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
@ -17,6 +37,7 @@ import appeng.services.version.Channel;
import appeng.services.version.Version; import appeng.services.version.Version;
import appeng.services.version.VersionCheckerConfig; import appeng.services.version.VersionCheckerConfig;
import appeng.services.version.VersionParser; import appeng.services.version.VersionParser;
import appeng.services.version.exceptions.VersionCheckerException;
public final class ReleaseFetcher 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 String GITHUB_RELEASES_URL = "https://api.github.com/repos/AppliedEnergistics/Applied-Energistics-2/releases";
private static final FormattedRelease EXCEPTIONAL_RELEASE = new MissingFormattedRelease(); private static final FormattedRelease EXCEPTIONAL_RELEASE = new MissingFormattedRelease();
@Nonnull
private final VersionCheckerConfig config; private final VersionCheckerConfig config;
@Nonnull
private final VersionParser parser; 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.config = config;
this.parser = parser; this.parser = parser;
@ -50,12 +73,20 @@ public final class ReleaseFetcher
return latestFitRelease; return latestFitRelease;
} }
catch( final Exception e ) catch( final VersionCheckerException e )
{ {
AELog.error( 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 private String getRawReleases( final URL url ) throws IOException
@ -63,7 +94,7 @@ public final class ReleaseFetcher
return IOUtils.toString( url ); return IOUtils.toString( url );
} }
private FormattedRelease getLatestFitRelease( final Iterable<Release> releases ) private FormattedRelease getLatestFitRelease( final Iterable<Release> releases ) throws VersionCheckerException
{ {
final String levelInConfig = this.config.level(); final String levelInConfig = this.config.level();
final Channel level = Channel.valueOf( levelInConfig ); final Channel level = Channel.valueOf( levelInConfig );

View file

@ -1,8 +1,16 @@
package appeng.services.version; package appeng.services.version;
import org.junit.Test; 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.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; 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_REVISION = "2-beta-8";
private static final String MOD_INVALID_CHANNEL = "rv2-gamma-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 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 ); private static final DefaultVersion VERSION = new DefaultVersion( 2, Channel.Beta, 8 );
@ -32,7 +42,7 @@ public final class VersionParserTest
} }
@Test @Test
public void testSameParsedGitHub() public void testSameParsedGitHub() throws VersionCheckerException
{ {
final Version version = this.parser.parse( GITHUB_VERSION ); final Version version = this.parser.parse( GITHUB_VERSION );
@ -40,50 +50,62 @@ public final class VersionParserTest
} }
@Test @Test
public void testParseGitHub() public void testParseGitHub() throws VersionCheckerException
{ {
assertTrue( this.parser.parse( GITHUB_VERSION ).equals( VERSION ) ); assertTrue( this.parser.parse( GITHUB_VERSION ).equals( VERSION ) );
} }
@Test( expected = AssertionError.class ) @Test( expected = InvalidRevisionException.class )
public void parseGH_InvalidRevision() public void parseGH_InvalidRevision() throws VersionCheckerException
{ {
assertFalse( this.parser.parse( GITHUB_INVALID_REVISION ).equals( VERSION ) ); assertFalse( this.parser.parse( GITHUB_INVALID_REVISION ).equals( VERSION ) );
} }
@Test( expected = AssertionError.class ) @Test( expected = InvalidChannelException.class )
public void parseGH_InvalidChannel() public void parseGH_InvalidChannel() throws VersionCheckerException
{ {
assertFalse( this.parser.parse( GITHUB_INVALID_CHANNEL ).equals( VERSION ) ); assertFalse( this.parser.parse( GITHUB_INVALID_CHANNEL ).equals( VERSION ) );
} }
@Test( expected = AssertionError.class ) @Test( expected = InvalidBuildException.class )
public void parseGH_InvalidBuild() public void parseGH_InvalidBuild() throws VersionCheckerException
{ {
assertFalse( this.parser.parse( GITHUB_INVALID_BUILD ).equals( VERSION ) ); assertFalse( this.parser.parse( GITHUB_INVALID_BUILD ).equals( VERSION ) );
} }
@Test @Test
public void testParseMod() public void testParseMod() throws VersionCheckerException
{ {
assertTrue( this.parser.parse( MOD_VERSION ).equals( VERSION ) ); assertTrue( this.parser.parse( MOD_VERSION ).equals( VERSION ) );
} }
@Test( expected = AssertionError.class ) @Test( expected = InvalidRevisionException.class )
public void parseMod_InvalidRevision() public void parseMod_InvalidRevision() throws VersionCheckerException
{ {
assertFalse( this.parser.parse( MOD_INVALID_REVISION ).equals( VERSION ) ); assertFalse( this.parser.parse( MOD_INVALID_REVISION ).equals( VERSION ) );
} }
@Test( expected = AssertionError.class ) @Test( expected = InvalidChannelException.class )
public void parseMod_InvalidChannel() public void parseMod_InvalidChannel() throws VersionCheckerException
{ {
assertFalse( this.parser.parse( MOD_INVALID_CHANNEL ).equals( VERSION ) ); assertFalse( this.parser.parse( MOD_INVALID_CHANNEL ).equals( VERSION ) );
} }
@Test( expected = AssertionError.class ) @Test( expected = InvalidBuildException.class )
public void parseMod_InvalidBuild() public void parseMod_InvalidBuild() throws VersionCheckerException
{ {
assertFalse( this.parser.parse( MOD_INVALID_BUILD ).equals( VERSION ) ); 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 ) );
}
} }