47592bcbcb
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.
200 lines
6.2 KiB
Java
200 lines
6.2 KiB
Java
/*
|
|
* 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;
|
|
}
|
|
}
|