All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.codehaus.mojo.license.download.PreferredFileNames Maven / Gradle / Ivy

There is a newer version: 2.4.0
Show newest version
package org.codehaus.mojo.license.download;

/*
 * #%L
 * License Maven Plugin
 * %%
 * Copyright (C) 2018 Codehaus
 * %%
 * This program 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.
 *
 * This program 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 General Lesser Public License for more details.
 *
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */

import java.io.File;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.regex.Pattern;

import org.apache.maven.plugin.logging.Log;
import org.codehaus.mojo.license.spdx.SpdxLicenseInfo;
import org.codehaus.mojo.license.spdx.SpdxLicenseInfo.Attachments.UrlInfo;
import org.codehaus.mojo.license.spdx.SpdxLicenseList;
import org.codehaus.mojo.license.utils.FileUtil;

/**
 * An url -> {@link FileNameEntry} mapping.
 *
 * @author Peter Palaga
 * @since 1.18
 */
// CHECKSTYLE_OFF: MethodLength
public class PreferredFileNames
{
    /**
     * @param licensesOutputDirectory
     * @param licenseUrlFileNames
     * @param log
     * @return a new {@link PreferredFileNames} built of AbstractDownloadLicensesMojo.licenseUrlFileNames
     */
    public static PreferredFileNames build( File licensesOutputDirectory, Map licenseUrlFileNames,
                                              Log log )
    {
        final Map>> fileNameToUrlPatterns = new LinkedHashMap<>();
        final Map sha1TofileName = new LinkedHashMap();


        if ( licenseUrlFileNames != null )
        {
            if ( licenseUrlFileNames.containsKey( "spdx" ) )
            {
                spdx( log, fileNameToUrlPatterns, sha1TofileName );
            }

            for ( Entry en : licenseUrlFileNames.entrySet() )
            {
                final String fileName = en.getKey();
                if ( fileName != null && !fileName.isEmpty() )
                {
                    if ( "spdx".equals( fileName ) )
                    {
                        // ignore
                    }
                    else if ( en.getValue() != null )
                    {
                        String[] rawPatters = en.getValue().split( "\\s+" );
                        if ( rawPatters != null )
                        {
                            final List patterns = new ArrayList<>();
                            String sha1 = null;
                            for ( String rawPattern : rawPatters )
                            {
                                if ( rawPattern.startsWith( "sha1:" ) )
                                {
                                    if ( sha1 != null )
                                    {
                                        throw new IllegalStateException( "sha1 defined twice for licenseFileName '"
                                            + fileName + "'" );
                                    }
                                    sha1 = rawPattern.substring( 5 );
                                }
                                else
                                {
                                    patterns.add( Pattern.compile( rawPattern, Pattern.CASE_INSENSITIVE ) );
                                }
                            }
                            if ( sha1 != null )
                            {
                                sha1TofileName.put( sha1, fileName );
                            }
                            fileNameToUrlPatterns.put( fileName,
                                    new AbstractMap.SimpleImmutableEntry<>(
                                                    sha1,
                                                    Collections.unmodifiableList( patterns ) ) );
                        }
                    }
                }
            }
        }
        return new PreferredFileNames( licensesOutputDirectory, fileNameToUrlPatterns, sha1TofileName, log );

    }

    private static  void spdx( Log log, Map>> result,
                              Map sha1TofileName )
    {
        final Map>> fileNameToUrlPatterns = new TreeMap<>();
        final SpdxLicenseList spdxList = SpdxLicenseList.getLatest();
        final Map lics = spdxList.getLicenses();
        log.info( "Honoring " + lics.size() + " SPDX licenses" );

        /* Count in how many licenses is the given sha1 used */
        final Map> sha1ToLicenseIds = new HashMap<>();
        final Map> sha1ToUrls = new HashMap<>();
        final Set stableSha1s = new HashSet<>();
        for ( SpdxLicenseInfo lic : lics.values() )
        {
            if ( !lic.isDeprecatedLicenseId() )
            {
                for ( Entry urlInfoEntry : lic.getAttachments().getUrlInfos().entrySet() )
                {
                    final UrlInfo urlInfo = urlInfoEntry.getValue();
                    if ( urlInfo.getSha1() != null && urlInfo.getMimeType() != null )
                    {
                        final String sha1 = urlInfo.getSha1();
                        if ( urlInfo.isStable() )
                        {
                            stableSha1s.add( sha1 );
                        }
                        Set licIds = sha1ToLicenseIds.get( sha1 );
                        if ( licIds == null )
                        {
                            licIds = new TreeSet<>();
                            sha1ToLicenseIds.put( sha1, licIds );
                        }
                        licIds.add( lic.getLicenseId() );

                        Set urls = sha1ToUrls.get( sha1 );
                        if ( urls == null )
                        {
                            urls = new TreeSet<>();
                            sha1ToUrls.put( sha1, urls );
                        }
                        urls.add( urlInfoEntry.getKey() );
                    }
                }
            }
        }
        /* For license sets in which a given sha1 is used, check if a . name would be unique */
        for ( Entry> sha1LicenseId : sha1ToLicenseIds.entrySet() )
        {
            final Set licIds = sha1LicenseId.getValue();
            final StringBuilder baseNameBuilder = new StringBuilder();
            final Map> mimeTypeToSha1 = new HashMap<>();
            for ( String licId : licIds )
            {
                if ( baseNameBuilder.length() > 0 )
                {
                    baseNameBuilder.append( "-OR-" );
                }
                baseNameBuilder.append( licId );

                final SpdxLicenseInfo lic = lics.get( licId );
                for ( Entry urlInfoEntry : lic.getAttachments().getUrlInfos().entrySet() )
                {
                    final UrlInfo urlInfo = urlInfoEntry.getValue();
                    final String mimeType = urlInfo.getMimeType();
                    if ( sha1ToLicenseIds.containsKey( urlInfo.getSha1() ) && mimeType != null )
                    {
                        Set sha1s = mimeTypeToSha1.get( mimeType );
                        if ( sha1s == null )
                        {
                            sha1s = new LinkedHashSet<>();
                            mimeTypeToSha1.put( mimeType, sha1s );
                        }
                        sha1s.add( urlInfo.getSha1() );
                    }
                }
            }
            final String baseName = baseNameBuilder.toString();

            for ( Entry> mimeTypeSha1 : mimeTypeToSha1.entrySet() )
            {
                final String mimeType = mimeTypeSha1.getKey();
                if ( mimeType == null )
                {
                    throw new IllegalStateException( "mimeType must not be null" );
                }
                final Set sha1s = mimeTypeSha1.getValue();
                for ( String sha1 : sha1s )
                {
                    final String uniqueName =
                                    sha1s.size() == 1 ? baseName : ( baseName + "-" + sha1.substring( 0, 7 ) );
                    final String fileName = uniqueName + FileUtil.toExtension( mimeType, true );
                    final List patterns = new ArrayList<>();

                    Set urls = sha1ToUrls.get( sha1 );
                    for ( String url : urls )
                    {
                        patterns.add( Pattern.compile( Pattern.quote( url ), Pattern.CASE_INSENSITIVE ) );
                    }

                    final String useSha1 = stableSha1s.contains( sha1 ) ? sha1 : null;
                    if ( useSha1 != null )
                    {
                        sha1TofileName.put( useSha1, fileName );
                    }
                    final List usePatterns = Collections.unmodifiableList( patterns );

                    final Entry> avail = fileNameToUrlPatterns.get( fileName );
                    if ( avail == null )
                    {
                        fileNameToUrlPatterns.put( fileName,
                                                   new AbstractMap.SimpleImmutableEntry<>( useSha1, usePatterns ) );
                    }
                    else if ( !( avail.getKey() == useSha1
                        || ( avail.getKey() != null && avail.getKey().equals( useSha1 ) ) )
                        || !isEqual( usePatterns, avail.getValue() ) )
                    {
                        log.warn( "Available: " + fileName + ", " + avail.getKey() + ", " + avail.getValue() );
                        log.warn( "To add   : " + fileName + ", " + useSha1 + ", " + patterns );
                        throw new IllegalStateException( fileName + " already present" );
                    }

                }
            }
        }

        if ( log.isDebugEnabled() )
        {
            final StringBuilder sb = new StringBuilder();
            sb.append( "\n" );

            for ( Entry>> en : fileNameToUrlPatterns.entrySet() )
            {
                final String fileName = en.getKey();
                final String sha1 = en.getValue().getKey();
                final List patterns = en.getValue().getValue();
                sb.append( "  <" + fileName + ">\n" );
                if ( sha1 != null )
                {
                    sb.append( "    sha1:" + sha1 + "\n" );
                }
                for ( Pattern pattern : patterns )
                {
                    sb.append( "    " + pattern.pattern() + "\n" );
                }
                sb.append( "  \n" );

            }
            sb.append( "\n" );
            log.debug( "SPDX licenseUrlFileNames:" );
            log.debug( sb.toString() );
        }
        result.putAll( fileNameToUrlPatterns );
    }

    private static boolean isEqual( final List newPatterns, List oldPatterns )
    {
        if ( oldPatterns.size() != newPatterns.size() )
        {
            return false;
        }
        final Iterator newIt = newPatterns.iterator();
        final Iterator oldIt = oldPatterns.iterator();
        while ( newIt.hasNext() )
        {
            if ( !newIt.next().pattern().equals( oldIt.next().pattern() ) )
            {
                return false;
            }
        }
        return true;
    }

    private final File licensesOutputDirectory;
    private final Map>> fileNameToUrlPatterns;
    private final Map sha1ToFileName;
    private final Log log;

    public PreferredFileNames( File licensesOutputDirectory,
                               Map>> fileNameToUrlPatterns,
                               Map sha1ToFileName, Log log )
    {
        super();
        this.licensesOutputDirectory = licensesOutputDirectory;
        this.fileNameToUrlPatterns = fileNameToUrlPatterns;
        this.sha1ToFileName = sha1ToFileName;
        this.log = log;
    }

    /**
     * @param sha1 the checksum to search by
     * @return a file name bound the given {@code sha1} checksum or {@code null}
     */
    public String getFileNameBySha1( String sha1 )
    {
        return sha1ToFileName.get( sha1 );
    }

    /**
     * @param url the URL to query
     * @return the preferred {@link FileNameEntry} for the given {@code url} or {@code null}
     */
    public FileNameEntry getEntryByUrl( String url )
    {
        for ( Entry>> fn : fileNameToUrlPatterns.entrySet() )
        {
            for ( Pattern pat : fn.getValue().getValue() )
            {
                if ( pat.matcher( url ).matches() )
                {
                    log.debug( "Using file name '" + fn.getKey() + "' for URL '" + url + "' that matched pattern '"
                        + pat.pattern() + "'" );
                    return new FileNameEntry( new File( licensesOutputDirectory, fn.getKey() ), true,
                                              fn.getValue().getKey() );
                }
            }
        }
        return null;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy