Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**
* Copyright 2018 Tobias Gierke
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.codesourcery.versiontracker.common;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.regex.Pattern;
public class Blacklist
{
private static final NeverMatcher NEVER_MATCHER = new NeverMatcher();
public static final class NeverMatcher extends VersionStringMatcher {
public NeverMatcher() {
super(".*", VersionMatcher.REGEX);
}
public boolean isIgnoredVersion(String s) {
return true;
}
}
/**
* Matcher used to decide whether some artifact version should be ignored while checking for updates.
*
* @author [email protected]
*/
public static class VersionStringMatcher
{
public final String pattern;
public final VersionMatcher type;
public transient volatile Pattern compiledPattern;
private VersionStringMatcher(String pattern, VersionMatcher type) {
Validate.notBlank(pattern,"pattern must not be NULL or blank");
Validate.notNull(type,"type must not be NULL");
this.pattern = pattern;
this.type = type;
if ( type == VersionMatcher.REGEX ) {
@SuppressWarnings("unused") // validate pattern has valid syntax
final Pattern tmp = Pattern.compile( pattern );
}
}
@Override
public boolean equals(Object other)
{
if ( other != null && getClass() == other.getClass() ) {
VersionStringMatcher o = (VersionStringMatcher) other;
return Objects.equals(this.pattern, o.pattern) &&
Objects.equals( this.type, o.type );
}
return false;
}
public void serialize(BinarySerializer serializer) throws IOException {
serializer.writeString( type.text );
serializer.writeString( pattern );
}
@Override
public String toString() {
return "IgnoreVersion["+type+"] = '"+pattern+"'";
}
@Override
public int hashCode() {
return 31 * (31 + pattern.hashCode()) + type.hashCode();
}
public boolean isIgnoredVersion(String s)
{
if ( s == null ) {
return false;
}
if ( type == VersionMatcher.EXACT ) {
return Objects.equals(s,pattern);
}
Pattern pat = compiledPattern;
if ( pat == null )
{
pat = Pattern.compile(pattern);
compiledPattern = pat;
}
return pat.matcher( s ).matches();
}
@JsonCreator
public static VersionStringMatcher createMatcher(@JsonProperty("pattern") String pattern, @JsonProperty("type") VersionMatcher type)
{
Validate.notBlank( pattern , "pattern must not be NULL or blank");
Validate.notNull(type,"type must not be NULL");
if ( VersionMatcher.REGEX.equals( type ) && ".*".equals( pattern ) ) {
return NEVER_MATCHER;
}
return new VersionStringMatcher(pattern,type);
}
public static VersionStringMatcher deserialize(BinarySerializer serializer) throws IOException
{
final String type = serializer.readString();
final String pattern = serializer.readString();
return VersionStringMatcher.createMatcher( pattern, VersionMatcher.fromString( type ) );
}
}
private final List globalIgnores = new ArrayList<>();
// key is group ID
private final Map> groupIdIgnores = new HashMap<>();
private final Map>> artifactIgnores = new HashMap<>();
public Blacklist() {
}
public boolean isEmpty() {
return ! isNotEmpty();
}
public boolean isNotEmpty() {
return ! globalIgnores.isEmpty() || ! groupIdIgnores.isEmpty() || ! artifactIgnores.isEmpty();
}
public void clear() {
globalIgnores.clear();
groupIdIgnores.clear();
artifactIgnores.clear();
}
@Override
public boolean equals(Object other)
{
if ( other instanceof Blacklist o ) {
if ( ! equals(this.globalIgnores, o.globalIgnores ) ) {
return false;
}
if ( ! equals(this.groupIdIgnores,o.groupIdIgnores) ) {
return false;
}
if ( artifactIgnores.size() != o.artifactIgnores.size() ) {
return false;
}
for ( Entry>> entry1 : this.artifactIgnores.entrySet() ) {
final String key = entry1.getKey();
final Map> map1 = entry1.getValue();
final Map> map2 = o.artifactIgnores.get(key);
if ( ! equals(map1,map2) ) {
return false;
}
}
return true;
}
return false;
}
public void serialize(BinarySerializer serializer) throws IOException
{
serializer.writeInt( globalIgnores.size() );
for ( VersionStringMatcher matcher : globalIgnores ) {
matcher.serialize(serializer);
}
serializer.writeInt( groupIdIgnores.size() );
for (Entry> entry : groupIdIgnores.entrySet() )
{
serializeMapEntry(entry,serializer);
}
serializer.writeInt( artifactIgnores.size() );
for ( Entry>> entry : artifactIgnores.entrySet() )
{
serializer.writeString( entry.getKey() );
final Map> map = entry.getValue();
serializer.writeInt( map.size() );
for ( Entry> entry2 : map.entrySet() )
{
serializeMapEntry(entry2,serializer);
}
}
}
private void serializeMapEntry(Entry> entry,BinarySerializer serializer) throws IOException {
serializer.writeString(entry.getKey());
serializer.writeInt( entry.getValue().size() );
for ( VersionStringMatcher matcher : entry.getValue() ) {
matcher.serialize(serializer);
}
}
public boolean isAllVersionsBlacklisted(String groupId,String artifactId) {
if ( containsNeverMatcher(globalIgnores) ) {
return true;
}
if ( containsNeverMatcher( getMatchersForGroupId( groupId ) ) ) {
return true;
}
Map> map1 = artifactIgnores.get( groupId );
return map1 != null && containsNeverMatcher( map1.get( artifactId ) );
}
/**
* Adds an ignored version pattern.
*
* This pattern will ignore any artifact version that matches the pattern.
*
* @param pattern
* @param matcher
*/
public void addIgnoredVersion(String pattern,VersionMatcher matcher)
{
final VersionStringMatcher newMatcher = VersionStringMatcher.createMatcher(pattern,matcher);
if ( ! globalIgnores.contains( newMatcher ) ) {
this.globalIgnores.add( newMatcher );
}
}
/**
* Adds an ignored version pattern.
*
* This pattern will ignore versions all artifacts that have a group ID equal to/starting with
* the group ID passed to this method.
*
* @param groupId groupId to ignore. Note that all sub-packages of this one will be ignored as well.
* @param pattern
* @param matcher
*/
public void addIgnoredVersion(String groupId,String pattern,VersionMatcher matcher)
{
Validate.notBlank( groupId , "groupId must not be NULL or blank");
List existing = groupIdIgnores.computeIfAbsent( groupId, k -> new ArrayList<>() );
VersionStringMatcher newMatcher = VersionStringMatcher.createMatcher(pattern,matcher);
if ( ! existing.contains( newMatcher ) ) {
existing.add( newMatcher);
}
}
/**
* Adds an ignored version pattern.
*
* This pattern will only ignore versions of artifacts with a matching artifact ID and group ID.
*
* @param groupId
* @param artifactId
* @param pattern
* @param matcher
*/
public void addIgnoredVersion(String groupId,String artifactId,String pattern,VersionMatcher matcher) {
Validate.notBlank( groupId , "groupId must not be NULL or blank");
Validate.notBlank( artifactId , "artifactId must not be NULL or blank");
Map> existing = artifactIgnores.computeIfAbsent( groupId, k -> new HashMap<>() );
List existingSet = existing.computeIfAbsent( artifactId, k -> new ArrayList<>() );
final VersionStringMatcher newMatcher = VersionStringMatcher.createMatcher(pattern,matcher );
if ( ! existingSet.contains( newMatcher ) ) {
existingSet.add( newMatcher );
}
}
public boolean isArtifactBlacklisted(Artifact artifact)
{
Validate.notBlank( artifact.groupId , "group ID must not be NULL or blank");
Validate.notBlank( artifact.artifactId , "artifact ID must not be NULL or blank");
Validate.notBlank( artifact.version , "artifact version must not be NULL or blank");
final String version = artifact.version;
if ( StringUtils.isNotBlank( version ) )
{
for ( VersionStringMatcher m : globalIgnores ) {
if ( m.isIgnoredVersion( version ) ) {
return true;
}
}
final List groupOnlyMatchers = getMatchersForGroupId( artifact.groupId );
for ( VersionStringMatcher m : groupOnlyMatchers ) {
if ( m.isIgnoredVersion( version ) ) {
return true;
}
}
Map> groupAndArtifact = artifactIgnores.get( artifact.groupId );
if ( groupAndArtifact != null )
{
final List matchers = groupAndArtifact.get( artifact.artifactId );
for ( VersionStringMatcher m : matchers ) {
if ( m.isIgnoredVersion( version ) ) {
return true;
}
}
}
}
return false;
}
private List getMatchersForGroupId(String artifactGroupId)
{
String mostSpecificMatch = null;
for ( String expectedGroupId : groupIdIgnores.keySet() )
{
// matching on group IDs is special as those rules actually apply to
// ANY artifact that the same group ID _OR_ has a group ID that is a
// CHILD of the group ID (so a group ID of "com.foo" is treated like "com.foo.*").
// See https://www.mojohaus.org/versions-maven-plugin/version-rules.html where it says:
// "Note: the groupId attribute in the rule elements has a lazy .* at the end, such that com.mycompany will match com.mycompany, com.mycompany.foo, com.mycompany.foo.bar, etc."
final boolean matches = artifactGroupId.equals( expectedGroupId ) || artifactGroupId.startsWith( expectedGroupId + "." );
// we'll only keep the most-specific match (longest prefix)
if ( matches && ( mostSpecificMatch == null || expectedGroupId.length() > mostSpecificMatch.length() ) )
{
mostSpecificMatch = expectedGroupId;
}
}
return mostSpecificMatch == null ? Collections.emptyList() : groupIdIgnores.get( mostSpecificMatch );
}
public boolean isVersionBlacklisted(String groupId, String artifactId, String version)
{
Validate.notBlank( groupId , "groupId must not be NULL or blank");
Validate.notBlank( artifactId , "artifactId must not be NULL or blank");
Validate.notBlank( version , "version must not be NULL or blank");
for ( VersionStringMatcher m : globalIgnores ) {
if ( m.isIgnoredVersion(version) ) {
return true;
}
}
List list = getMatchersForGroupId( groupId );
for ( VersionStringMatcher m : list ) {
if ( m.isIgnoredVersion( version ) ) {
return true;
}
}
final Map> map = artifactIgnores.get( groupId );
if ( map != null ) {
list = map.get( artifactId );
if ( list != null ) {
for ( VersionStringMatcher m : list ) {
if ( m.isIgnoredVersion( version )) {
return true;
}
}
}
}
return false;
}
public enum VersionMatcher
{
@JsonProperty("exact")
EXACT("exact"),
@JsonProperty("regex")
REGEX("regex");
public final String text;
VersionMatcher(String text) {
this.text = text;
}
public static VersionMatcher fromString(String s)
{
return switch ( s.toLowerCase() ) {
case "exact" -> VersionMatcher.EXACT;
case "regex" -> VersionMatcher.REGEX;
default -> throw new IllegalArgumentException( "Unsupported version matcher type: '" + s + "'" );
};
}
}
private static boolean equals(Map> m1,Map> m2 ) {
if ( m1.size() != m2.size() ) {
return false;
}
for ( Entry> entry : m1.entrySet() ) {
final List l1 = entry.getValue();
final List l2 = m2.get( entry.getKey() );
if ( ! equals(l1,l2) ) {
return false;
}
}
return true;
}
private static boolean equals(List l1,List l2) {
if ( l1 == null || l2 == null ) {
return l1 == l2;
}
if ( l1.size() != l2.size() ) {
return false;
}
for ( VersionStringMatcher m1 : l1 ) {
if ( l2.stream().noneMatch( x -> x.equals( m1 ) ) ) {
return false;
}
}
return true;
}
private static void deserializeMapEntry(Map> map,BinarySerializer serializer) throws IOException
{
final String key = serializer.readString();
int count = serializer.readInt();
final List list = new ArrayList<>( count );
for ( ; count > 0 ; count-- ) {
list.add( VersionStringMatcher.deserialize(serializer) );
}
map.put( key , list );
}
public static Blacklist deserialize(BinarySerializer serializer) throws IOException
{
final Blacklist result = new Blacklist();
for ( int count = serializer.readInt() ; count > 0 ; count--) {
result.globalIgnores.add( VersionStringMatcher.deserialize( serializer ) );
}
for ( int count = serializer.readInt() ; count > 0 ; count--) {
deserializeMapEntry(result.groupIdIgnores,serializer);
}
for ( int count = serializer.readInt() ; count > 0 ; count-- )
{
final String key = serializer.readString();
int count2 = serializer.readInt();
final Map> map = new HashMap<>( count2 );
for ( ; count2 > 0 ; count2-- ) {
deserializeMapEntry(map,serializer);
}
result.artifactIgnores.put( key , map );
}
return result;
}
private static boolean containsNeverMatcher(List list) {
return list != null && list.contains( NEVER_MATCHER );
}
}