/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.maven.buildcache;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.regex.Pattern;
import javax.annotation.Nonnull;
import javax.inject.Inject;
import javax.inject.Named;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.mutable.MutableBoolean;
import org.apache.maven.SessionScoped;
import org.apache.maven.artifact.handler.ArtifactHandler;
import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
import org.apache.maven.buildcache.artifact.RestoredArtifact;
import org.apache.maven.buildcache.hash.HashAlgorithm;
import org.apache.maven.buildcache.hash.HashFactory;
import org.apache.maven.buildcache.xml.Build;
import org.apache.maven.buildcache.xml.CacheConfig;
import org.apache.maven.buildcache.xml.CacheSource;
import org.apache.maven.buildcache.xml.DtoUtils;
import org.apache.maven.buildcache.xml.XmlService;
import org.apache.maven.buildcache.xml.build.Artifact;
import org.apache.maven.buildcache.xml.build.CompletedExecution;
import org.apache.maven.buildcache.xml.build.DigestItem;
import org.apache.maven.buildcache.xml.build.ProjectsInputInfo;
import org.apache.maven.buildcache.xml.build.Scm;
import org.apache.maven.buildcache.xml.config.PropertyName;
import org.apache.maven.buildcache.xml.config.TrackedProperty;
import org.apache.maven.buildcache.xml.diff.Diff;
import org.apache.maven.buildcache.xml.report.CacheReport;
import org.apache.maven.buildcache.xml.report.ProjectReport;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.execution.MojoExecutionEvent;
import org.apache.maven.plugin.Mojo;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.descriptor.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectHelper;
import org.apache.maven.repository.RepositorySystem;
import org.codehaus.plexus.util.ReflectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static java.nio.file.StandardOpenOption.CREATE;
import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.commons.lang3.StringUtils.replace;
import static org.apache.commons.lang3.StringUtils.split;
import static org.apache.maven.buildcache.CacheResult.empty;
import static org.apache.maven.buildcache.CacheResult.failure;
import static org.apache.maven.buildcache.CacheResult.partialSuccess;
import static org.apache.maven.buildcache.CacheResult.rebuilded;
import static org.apache.maven.buildcache.CacheResult.success;
import static org.apache.maven.buildcache.HttpCacheRepositoryImpl.BUILDINFO_XML;
import static org.apache.maven.buildcache.checksum.KeyUtils.getVersionlessProjectKey;
import static org.apache.maven.buildcache.checksum.MavenProjectInput.CACHE_IMPLEMENTATION_VERSION;

/**
 * CacheControllerImpl
 */
@SessionScoped
@Named
@SuppressWarnings( "unused" )
public class CacheControllerImpl implements CacheController
{

    public static final String FILE_SEPARATOR_SUBST = "_";

    /**
     * Prefix for generated sources stored as a separate artifact in cache
     */
    private static final String BUILD_PREFIX = "build" + FILE_SEPARATOR_SUBST;

    private static final Logger LOGGER = LoggerFactory.getLogger( CacheControllerImpl.class );

    private final MavenProjectHelper projectHelper;

    private final ArtifactHandlerManager artifactHandlerManager;

    private final XmlService xmlService;

    private final CacheConfig cacheConfig;

    private final LocalCacheRepository localCache;

    private final RemoteCacheRepository remoteCache;

    private final ConcurrentMap<String, CacheResult> cacheResults = new ConcurrentHashMap<>();

    private final LifecyclePhasesHelper lifecyclePhasesHelper;

    private volatile Map<String, MavenProject> projectIndex;

    private final ProjectInputCalculator projectInputCalculator;

    private final RestoredArtifactHandler restoreArtifactHandler;

    private volatile Scm scm;

    @Inject
    @SuppressWarnings( "checkstyle:ParameterNumber" )
    public CacheControllerImpl(
                    MavenProjectHelper projectHelper,
                    RepositorySystem repoSystem,
                    ArtifactHandlerManager artifactHandlerManager,
                    XmlService xmlService,
                    LocalCacheRepository localCache,
                    RemoteCacheRepository remoteCache,
                    CacheConfig cacheConfig,
                    ProjectInputCalculator projectInputCalculator,
                    RestoredArtifactHandler restoreArtifactHandler,
                    LifecyclePhasesHelper lifecyclePhasesHelper,
                    MavenSession session )
    {
        this.projectHelper = projectHelper;
        this.localCache = localCache;
        this.remoteCache = remoteCache;
        this.cacheConfig = cacheConfig;
        this.artifactHandlerManager = artifactHandlerManager;
        this.xmlService = xmlService;
        this.lifecyclePhasesHelper = lifecyclePhasesHelper;
        this.projectInputCalculator = projectInputCalculator;
        this.restoreArtifactHandler = restoreArtifactHandler;
    }

    @Override
    @Nonnull
    public CacheResult findCachedBuild( MavenSession session, MavenProject project,
                    List<MojoExecution> mojoExecutions )
    {
        final String highestRequestPhase = CacheUtils.getLast( mojoExecutions ).getLifecyclePhase();
        if ( !lifecyclePhasesHelper.isLaterPhaseThanClean( highestRequestPhase ) )
        {
            return empty();
        }

        LOGGER.info( "Attempting to restore project from build cache" );

        ProjectsInputInfo inputInfo = projectInputCalculator.calculateInput( project );

        final CacheContext context = new CacheContext( project, inputInfo, session );
        // remote build first
        CacheResult result = findCachedBuild( mojoExecutions, context );

        if ( !result.isSuccess() && result.getContext() != null )
        {
            LOGGER.debug( "Remote cache is incomplete or missing, trying local build" );

            CacheResult localBuild = findLocalBuild( mojoExecutions, context );

            if ( localBuild.isSuccess() || ( localBuild.isPartialSuccess() && !result.isPartialSuccess() ) )
            {
                result = localBuild;
            }
            else
            {
                LOGGER.info( "Local build was not found by checksum " + inputInfo.getChecksum() );
            }
        }
        cacheResults.put( getVersionlessProjectKey( project ), result );

        return result;
    }

    private CacheResult findCachedBuild( List<MojoExecution> mojoExecutions, CacheContext context )
    {
        Optional<Build> cachedBuild = Optional.empty();
        try
        {
            cachedBuild = localCache.findBuild( context );
            if ( cachedBuild.isPresent() )
            {
                return analyzeResult( context, mojoExecutions, cachedBuild.get() );
            }
        }
        catch ( Exception e )
        {
            LOGGER.error( "Cannot read cached remote build", e );
        }
        return cachedBuild.map( build -> failure( build, context ) )
                        .orElseGet( () -> empty( context ) );
    }

    private CacheResult findLocalBuild( List<MojoExecution> mojoExecutions, CacheContext context )
    {
        Optional<Build> localBuild = Optional.empty();
        try
        {
            localBuild = localCache.findLocalBuild( context );
            if ( localBuild.isPresent() )
            {
                return analyzeResult( context, mojoExecutions, localBuild.get() );
            }
        }
        catch ( Exception e )
        {
            LOGGER.error( "Cannot read local build", e );
        }
        return localBuild.map( build -> failure( build, context ) )
                        .orElseGet( () -> empty( context ) );
    }

    private CacheResult analyzeResult( CacheContext context, List<MojoExecution> mojoExecutions, Build build )
    {
        try
        {
            final ProjectsInputInfo inputInfo = context.getInputInfo();

            LOGGER.info( "Found cached build, restoring from cache {}", inputInfo.getChecksum() );
            LOGGER.debug( "Cached build details: {}", build );

            final String cacheImplementationVersion = build.getCacheImplementationVersion();
            if ( !CACHE_IMPLEMENTATION_VERSION.equals( cacheImplementationVersion ) )
            {
                LOGGER.warn(
                                "Maven and cached build implementations mismatch, caching might not work correctly. "
                                                + "Implementation version: " + CACHE_IMPLEMENTATION_VERSION
                                                + ", cached build: {}",
                                build.getCacheImplementationVersion() );
            }

            List<MojoExecution> cachedSegment = lifecyclePhasesHelper.getCachedSegment( mojoExecutions, build );
            List<MojoExecution> missingMojos = build.getMissingExecutions( cachedSegment );
            if ( !missingMojos.isEmpty() )
            {
                LOGGER.warn( "Cached build doesn't contains all requested plugin executions "
                                + "(missing: {}), cannot restore", missingMojos );
                return failure( build, context );
            }

            if ( !isCachedSegmentPropertiesPresent( context.getProject(), build, cachedSegment ) )
            {
                LOGGER.info( "Cached build violates cache rules, cannot restore" );
                return failure( build, context );
            }

            final String highestRequestPhase = CacheUtils.getLast( mojoExecutions ).getLifecyclePhase();
            if ( lifecyclePhasesHelper.isLaterPhaseThanBuild( highestRequestPhase, build )
                            && !canIgnoreMissingSegment( build, mojoExecutions ) )
            {
                LOGGER.info( "Project restored partially. Highest cached goal: {}, requested: {}",
                                build.getHighestCompletedGoal(), highestRequestPhase );
                return partialSuccess( build, context );
            }

            return success( build, context );

        }
        catch ( Exception e )
        {
            LOGGER.error( "Failed to restore project", e );
            localCache.clearCache( context );
            return failure( build, context );
        }
    }

    private boolean canIgnoreMissingSegment( Build info, List<MojoExecution> mojoExecutions )
    {
        final List<MojoExecution> postCachedSegment = lifecyclePhasesHelper.getPostCachedSegment( mojoExecutions,
                        info );
        for ( MojoExecution mojoExecution : postCachedSegment )
        {
            if ( !cacheConfig.canIgnore( mojoExecution ) )
            {
                return false;
            }
        }
        return true;
    }

    @Override
    public boolean restoreProjectArtifacts( CacheResult cacheResult )
    {
        final Build build = cacheResult.getBuildInfo();
        final CacheContext context = cacheResult.getContext();
        final MavenProject project = context.getProject();

        try
        {
            RestoredArtifact restoredProjectArtifact = null;
            List<RestoredArtifact> restoredAttachedArtifacts = new ArrayList<>();

            if ( build.getArtifact() != null && isNotBlank( build.getArtifact().getFileName() ) )
            {
                final Artifact artifactInfo = build.getArtifact();
                String originalVersion = artifactInfo.getVersion();
                artifactInfo.setVersion( project.getVersion() );
                // TODO if remote is forced, probably need to refresh or reconcile all files
                final Future<File> downloadTask = createDownloadTask(
                                cacheResult,
                                context,
                                project,
                                artifactInfo,
                                originalVersion );
                restoredProjectArtifact = restoredArtifact( project.getArtifact(), artifactInfo.getType(),
                                artifactInfo.getClassifier(),
                                downloadTask );
            }

            for ( Artifact attachedArtifactInfo : build.getAttachedArtifacts() )
            {
                String originalVersion = attachedArtifactInfo.getVersion();
                attachedArtifactInfo.setVersion( project.getVersion() );
                if ( isNotBlank( attachedArtifactInfo.getFileName() ) )
                {
                    if ( StringUtils.startsWith( attachedArtifactInfo.getClassifier(), BUILD_PREFIX ) )
                    {
                        // restoring generated sources might be unnecessary in CI, could be disabled for
                        // performance reasons
                        if ( cacheConfig.isRestoreGeneratedSources() )
                        {
                            // generated sources artifact
                            final Path attachedArtifactFile = localCache.getArtifactFile( context,
                                            cacheResult.getSource(), attachedArtifactInfo );
                            restoreGeneratedSources( attachedArtifactInfo, attachedArtifactFile, project );
                        }
                    }
                    else
                    {
                        Future<File> downloadTask = createDownloadTask(
                                        cacheResult,
                                        context,
                                        project,
                                        attachedArtifactInfo,
                                        originalVersion );
                        final RestoredArtifact restoredAttachedArtifact = restoredArtifact(
                                        restoredProjectArtifact == null ? project.getArtifact()
                                                        : restoredProjectArtifact,
                                        attachedArtifactInfo.getType(),
                                        attachedArtifactInfo.getClassifier(),
                                        downloadTask );
                        restoredAttachedArtifacts.add( restoredAttachedArtifact );
                    }
                }
            }
            // Actually modify project at the end in case something went wrong during restoration,
            // in which case, the project is unmodified and we continue with normal build.
            if ( restoredProjectArtifact != null )
            {
                project.setArtifact( restoredProjectArtifact );
            }
            restoredAttachedArtifacts.forEach( project::addAttachedArtifact );
            return true;
        }
        catch ( Exception e )
        {
            LOGGER.debug( "Cannot restore cache, continuing with normal build.", e );
            return false;
        }
    }

    /**
     * Helper method similar to {@link org.apache.maven.project.MavenProjectHelper#attachArtifact} to work specifically
     * with restored from cache artifacts
     */
    private RestoredArtifact restoredArtifact( org.apache.maven.artifact.Artifact parent, String artifactType,
                    String artifactClassifier,
                    Future<File> artifactFile )
    {
        ArtifactHandler handler = null;

        if ( artifactType != null )
        {
            handler = artifactHandlerManager.getArtifactHandler( artifactType );
        }

        if ( handler == null )
        {
            handler = artifactHandlerManager.getArtifactHandler( "jar" );
        }

        // todo: probably need update download url to cache
        RestoredArtifact artifact = new RestoredArtifact( parent, artifactFile, artifactType, artifactClassifier,
                        handler );
        artifact.setResolved( true );

        return artifact;
    }

    private Future<File> createDownloadTask( CacheResult cacheResult, CacheContext context, MavenProject project,
                    Artifact artifact, String originalVersion )
    {
        final FutureTask<File> downloadTask = new FutureTask<>( () ->
        {
            LOGGER.debug( "Downloading artifact {}", artifact.getArtifactId() );
            final Path artifactFile = localCache.getArtifactFile( context, cacheResult.getSource(),
                            artifact );
            if ( !Files.exists( artifactFile ) )
            {
                throw new FileNotFoundException(
                                "Missing file for cached build, cannot restore. File: " + artifactFile );
            }
            LOGGER.debug( "Downloaded artifact " + artifact.getArtifactId() + " to: " + artifactFile );
            return restoreArtifactHandler.adjustArchiveArtifactVersion(
                            project,
                            originalVersion,
                            artifactFile ).toFile();
        } );
        if ( !cacheConfig.isLazyRestore() )
        {
            downloadTask.run();
        }
        return downloadTask;
    }

    @Override
    public void save( CacheResult cacheResult, List<MojoExecution> mojoExecutions,
                    Map<String, MojoExecutionEvent> executionEvents )
    {
        CacheContext context = cacheResult.getContext();

        if ( context == null || context.getInputInfo() == null )
        {
            LOGGER.info( "Cannot save project in cache, skipping" );
            return;
        }

        final MavenProject project = context.getProject();
        final MavenSession session = context.getSession();
        try
        {
            final HashFactory hashFactory = cacheConfig.getHashFactory();
            final org.apache.maven.artifact.Artifact projectArtifact = project.getArtifact();
            final List<org.apache.maven.artifact.Artifact> attachedArtifacts;
            final List<Artifact> attachedArtifactDtos;
            final Artifact projectArtifactDto;
            if ( project.hasLifecyclePhase( "package" ) )
            {
                final HashAlgorithm algorithm = hashFactory.createAlgorithm();
                attachGeneratedSources( project );
                attachOutputs( project );
                attachedArtifacts = project.getAttachedArtifacts() != null
                                ? project.getAttachedArtifacts() : Collections.emptyList();
                attachedArtifactDtos = artifactDtos( attachedArtifacts, algorithm );
                projectArtifactDto = artifactDto( project.getArtifact(), algorithm );
            }
            else
            {
                attachedArtifacts = Collections.emptyList();
                attachedArtifactDtos = new ArrayList<>();
                projectArtifactDto = null;
            }

            List<CompletedExecution> completedExecution = buildExecutionInfo( mojoExecutions, executionEvents );

            final Build build = new Build( session.getGoals(), projectArtifactDto, attachedArtifactDtos,
                            context.getInputInfo(), completedExecution, hashFactory.getAlgorithm() );
            populateGitInfo( build, session );
            build.getDto().set_final( cacheConfig.isSaveFinal() );
            cacheResults.put( getVersionlessProjectKey( project ), rebuilded( cacheResult, build ) );

            // if package phase presence means new artifacts were packaged
            if ( project.hasLifecyclePhase( "package" ) )
            {
                localCache.beforeSave( context );
                localCache.saveBuildInfo( cacheResult, build );
                if ( projectArtifact.getFile() != null )
                {
                    localCache.saveArtifactFile( cacheResult, projectArtifact );
                }
                for ( org.apache.maven.artifact.Artifact attachedArtifact : attachedArtifacts )
                {
                    if ( attachedArtifact.getFile() != null && isOutputArtifact(
                                    attachedArtifact.getFile().getName() ) )
                    {
                        localCache.saveArtifactFile( cacheResult, attachedArtifact );
                    }
                }
            }
            else
            {
                localCache.saveBuildInfo( cacheResult, build );
            }

            if ( cacheConfig.isBaselineDiffEnabled() )
            {
                produceDiffReport( cacheResult, build );
            }

        }
        catch ( Exception e )
        {
            LOGGER.error( "Failed to save project, cleaning cache. Project: {}", project, e );
            try
            {
                localCache.clearCache( context );
            }
            catch ( Exception ex )
            {
                LOGGER.error( "Failed to clean cache due to unexpected error:", ex );
            }
        }
    }

    public void produceDiffReport( CacheResult cacheResult, Build build )
    {
        MavenProject project = cacheResult.getContext().getProject();
        Optional<Build> baselineHolder = remoteCache.findBaselineBuild( project );
        if ( baselineHolder.isPresent() )
        {
            Build baseline = baselineHolder.get();
            String outputDirectory = project.getBuild().getDirectory();
            Path reportOutputDir = Paths.get( outputDirectory, "incremental-maven" );
            LOGGER.info( "Saving cache builds diff to: {}", reportOutputDir );
            Diff diff = new CacheDiff( build.getDto(), baseline.getDto(), cacheConfig ).compare();
            try
            {
                Files.createDirectories( reportOutputDir );
                final ProjectsInputInfo baselineInputs = baseline.getDto().getProjectsInputInfo();
                final String checksum = baselineInputs.getChecksum();
                Files.write( reportOutputDir.resolve( "buildinfo-baseline-" + checksum + ".xml" ),
                                xmlService.toBytes( baseline.getDto() ), TRUNCATE_EXISTING, CREATE );
                Files.write( reportOutputDir.resolve( "buildinfo-" + checksum + ".xml" ),
                                xmlService.toBytes( build.getDto() ), TRUNCATE_EXISTING, CREATE );
                Files.write( reportOutputDir.resolve( "buildsdiff-" + checksum + ".xml" ),
                                xmlService.toBytes( diff ), TRUNCATE_EXISTING, CREATE );
                final Optional<DigestItem> pom = CacheDiff.findPom( build.getDto().getProjectsInputInfo() );
                if ( pom.isPresent() )
                {
                    Files.write( reportOutputDir.resolve( "effective-pom-" + checksum + ".xml" ),
                                    pom.get().getValue().getBytes( StandardCharsets.UTF_8 ),
                                    TRUNCATE_EXISTING, CREATE );
                }
                final Optional<DigestItem> baselinePom = CacheDiff.findPom( baselineInputs );
                if ( baselinePom.isPresent() )
                {
                    Files.write( reportOutputDir.resolve(
                                    "effective-pom-baseline-" + baselineInputs.getChecksum() + ".xml" ),
                                    baselinePom.get().getValue().getBytes( StandardCharsets.UTF_8 ),
                                    TRUNCATE_EXISTING, CREATE );
                }
            }
            catch ( IOException e )
            {
                LOGGER.error( "Cannot produce build diff for project", e );
            }
        }
        else
        {
            LOGGER.info( "Cannot find project in baseline build, skipping diff" );
        }
    }

    private List<Artifact> artifactDtos( List<org.apache.maven.artifact.Artifact> attachedArtifacts,
                    HashAlgorithm digest ) throws IOException
    {
        List<Artifact> result = new ArrayList<>();
        for ( org.apache.maven.artifact.Artifact attachedArtifact : attachedArtifacts )
        {
            if ( attachedArtifact.getFile() != null && isOutputArtifact( attachedArtifact.getFile().getName() ) )
            {
                result.add( artifactDto( attachedArtifact, digest ) );
            }
        }
        return result;
    }

    private Artifact artifactDto( org.apache.maven.artifact.Artifact projectArtifact,
                    HashAlgorithm algorithm ) throws IOException
    {
        final Artifact dto = DtoUtils.createDto( projectArtifact );
        if ( projectArtifact.getFile() != null && projectArtifact.getFile().isFile() )
        {
            final Path file = projectArtifact.getFile().toPath();
            dto.setFileHash( algorithm.hash( file ) );
            dto.setFileSize( Files.size( file ) );
        }
        return dto;
    }

    private List<CompletedExecution> buildExecutionInfo( List<MojoExecution> mojoExecutions,
                    Map<String, MojoExecutionEvent> executionEvents )
    {
        List<CompletedExecution> list = new ArrayList<>();
        for ( MojoExecution mojoExecution : mojoExecutions )
        {
            final String executionKey = CacheUtils.mojoExecutionKey( mojoExecution );
            final MojoExecutionEvent executionEvent = executionEvents != null ? executionEvents.get( executionKey )
                            : null;
            CompletedExecution executionInfo = new CompletedExecution();
            executionInfo.setExecutionKey( executionKey );
            executionInfo.setMojoClassName( mojoExecution.getMojoDescriptor().getImplementation() );
            if ( executionEvent != null )
            {
                recordMojoProperties( executionInfo, executionEvent );
            }
            list.add( executionInfo );
        }
        return list;
    }

    private void recordMojoProperties( CompletedExecution execution, MojoExecutionEvent executionEvent )
    {
        final MojoExecution mojoExecution = executionEvent.getExecution();

        final boolean logAll = cacheConfig.isLogAllProperties( mojoExecution );
        List<TrackedProperty> trackedProperties = cacheConfig.getTrackedProperties( mojoExecution );
        List<PropertyName> noLogProperties = cacheConfig.getNologProperties( mojoExecution );
        List<PropertyName> forceLogProperties = cacheConfig.getLoggedProperties( mojoExecution );
        final Mojo mojo = executionEvent.getMojo();

        final File baseDir = executionEvent.getProject().getBasedir();
        final String baseDirPath = FilenameUtils.normalizeNoEndSeparator( baseDir.getAbsolutePath() ) + File.separator;

        final List<Parameter> parameters = mojoExecution.getMojoDescriptor().getParameters();
        for ( Parameter parameter : parameters )
        {
            // editable parameters could be configured by user
            if ( !parameter.isEditable() )
            {
                continue;
            }

            final String propertyName = parameter.getName();
            final boolean tracked = isTracked( propertyName, trackedProperties );
            if ( !tracked && isExcluded( propertyName, logAll, noLogProperties, forceLogProperties ) )
            {
                continue;
            }

            try
            {
                final Object value = ReflectionUtils.getValueIncludingSuperclasses( propertyName, mojo );
                DtoUtils.addProperty( execution, propertyName, value, baseDirPath, tracked );
            }
            catch ( IllegalAccessException e )
            {
                LOGGER.info( "Cannot get property {} value from {}: {}", propertyName, mojo, e.getMessage() );
                if ( tracked )
                {
                    throw new IllegalArgumentException( "Property configured in cache introspection config "
                                    + "for " + mojo + " is not accessible: " + propertyName );
                }
            }
        }
    }

    private boolean isExcluded( String propertyName, boolean logAll, List<PropertyName> excludedProperties,
                    List<PropertyName> forceLogProperties )
    {
        if ( !forceLogProperties.isEmpty() )
        {
            for ( PropertyName logProperty : forceLogProperties )
            {
                if ( StringUtils.equals( propertyName, logProperty.getPropertyName() ) )
                {
                    return false;
                }
            }
            return true;
        }

        if ( !excludedProperties.isEmpty() )
        {
            for ( PropertyName excludedProperty : excludedProperties )
            {
                if ( StringUtils.equals( propertyName, excludedProperty.getPropertyName() ) )
                {
                    return true;
                }
            }
            return false;
        }

        return !logAll;
    }

    private boolean isTracked( String propertyName, List<TrackedProperty> trackedProperties )
    {
        for ( TrackedProperty trackedProperty : trackedProperties )
        {
            if ( StringUtils.equals( propertyName, trackedProperty.getPropertyName() ) )
            {
                return true;
            }
        }
        return false;
    }

    private boolean isCachedSegmentPropertiesPresent( MavenProject project, Build build,
                    List<MojoExecution> mojoExecutions )
    {
        for ( MojoExecution mojoExecution : mojoExecutions )
        {
            // completion of all mojos checked above, so we expect tp have execution info here
            final List<TrackedProperty> trackedProperties = cacheConfig.getTrackedProperties( mojoExecution );
            final CompletedExecution cachedExecution = build.findMojoExecutionInfo( mojoExecution );

            if ( cachedExecution == null )
            {
                LOGGER.info( "Execution is not cached. Plugin: {}, goal {}",
                                mojoExecution.getExecutionId(), mojoExecution.getGoal() );
                return false;
            }

            if ( !DtoUtils.containsAllProperties( cachedExecution, trackedProperties ) )
            {
                LOGGER.info( "Build info doesn't match rules. Plugin: {}",
                                mojoExecution.getExecutionId() );
                return false;
            }
        }
        return true;
    }

    @Override
    public boolean isForcedExecution( MavenProject project, MojoExecution execution )
    {
        if ( cacheConfig.isForcedExecution( execution ) )
        {
            return true;
        }

        if ( StringUtils.isNotBlank( cacheConfig.getAlwaysRunPlugins() ) )
        {
            String[] alwaysRunPluginsList = split( cacheConfig.getAlwaysRunPlugins(), "," );
            for ( String pluginAndGoal : alwaysRunPluginsList )
            {
                String[] tokens = pluginAndGoal.split( ":" );
                String alwaysRunPlugin = tokens[0];
                String alwaysRunGoal = tokens.length == 1 ? "*" : tokens[1];
                if ( Objects.equals( execution.getPlugin().getArtifactId(), alwaysRunPlugin )
                                && ( "*".equals( alwaysRunGoal )
                                                || Objects.equals( execution.getGoal(), alwaysRunGoal ) ) )
                {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public void saveCacheReport( MavenSession session )
    {
        try
        {
            CacheReport cacheReport = new CacheReport();
            for ( CacheResult result : cacheResults.values() )
            {
                ProjectReport projectReport = new ProjectReport();
                CacheContext context = result.getContext();
                MavenProject project = context.getProject();
                projectReport.setGroupId( project.getGroupId() );
                projectReport.setArtifactId( project.getArtifactId() );
                projectReport.setChecksum( context.getInputInfo().getChecksum() );
                boolean checksumMatched = result.getStatus() != RestoreStatus.EMPTY;
                projectReport.setChecksumMatched( checksumMatched );
                projectReport.setLifecycleMatched( checksumMatched && result.isSuccess() );
                projectReport.setSource( String.valueOf( result.getSource() ) );
                if ( result.getSource() == CacheSource.REMOTE )
                {
                    projectReport.setUrl( remoteCache.getResourceUrl( context, BUILDINFO_XML ) );
                }
                else if ( result.getSource() == CacheSource.BUILD && cacheConfig.isSaveToRemote() )
                {
                    projectReport.setSharedToRemote( true );
                    projectReport.setUrl( remoteCache.getResourceUrl( context, BUILDINFO_XML ) );
                }
                cacheReport.addProject( projectReport );
            }

            String buildId = UUID.randomUUID().toString();
            localCache.saveCacheReport( buildId, session, cacheReport );
        }
        catch ( Exception e )
        {
            LOGGER.error( "Cannot save incremental build aggregated report", e );
        }
    }

    private void populateGitInfo( Build build, MavenSession session )
    {
        if ( scm == null )
        {
            synchronized ( this )
            {
                if ( scm == null )
                {
                    try
                    {
                        scm = CacheUtils.readGitInfo( session );
                    }
                    catch ( IOException e )
                    {
                        scm = new Scm();
                        LOGGER.error( "Cannot populate git info", e );
                    }
                }
            }
        }
        build.getDto().setScm( scm );
    }

    private void zipAndAttachArtifact( MavenProject project, Path dir, String classifier ) throws IOException
    {
        Path temp = Files.createTempFile( "maven-incremental", project.getArtifactId() );
        temp.toFile().deleteOnExit();
        CacheUtils.zip( dir, temp );
        projectHelper.attachArtifact( project, "zip", classifier, temp.toFile() );
    }

    private String pathToClassifier( Path relative )
    {
        final int nameCount = relative.getNameCount();
        List<String> segments = new ArrayList<>( nameCount + 1 );
        for ( int i = 0; i < nameCount; i++ )
        {
            segments.add( relative.getName( i ).toFile().getName() );
        }
        // todo handle _ in file names
        return BUILD_PREFIX + StringUtils.join( segments.iterator(), FILE_SEPARATOR_SUBST );
    }

    private Path classifierToPath( Path outputDir, String classifier )
    {
        classifier = StringUtils.removeStart( classifier, BUILD_PREFIX );
        final String relPath = replace( classifier, FILE_SEPARATOR_SUBST, File.separator );
        return outputDir.resolve( relPath );
    }

    private void restoreGeneratedSources( Artifact artifact, Path artifactFilePath, MavenProject project )
                    throws IOException
    {
        final Path targetDir = Paths.get( project.getBuild().getDirectory() );
        final Path outputDir = classifierToPath( targetDir, artifact.getClassifier() );
        if ( Files.exists( outputDir ) )
        {
            FileUtils.cleanDirectory( outputDir.toFile() );
        }
        else
        {
            Files.createDirectories( outputDir );
        }
        CacheUtils.unzip( artifactFilePath, outputDir );
    }

    // TODO: move to config
    public void attachGeneratedSources( MavenProject project ) throws IOException
    {
        final Path targetDir = Paths.get( project.getBuild().getDirectory() );

        final Path generatedSourcesDir = targetDir.resolve( "generated-sources" );
        attachDirIfNotEmpty( generatedSourcesDir, targetDir, project );

        final Path generatedTestSourcesDir = targetDir.resolve( "generated-test-sources" );
        attachDirIfNotEmpty( generatedTestSourcesDir, targetDir, project );

        Set<String> sourceRoots = new TreeSet<>();
        if ( project.getCompileSourceRoots() != null )
        {
            sourceRoots.addAll( project.getCompileSourceRoots() );
        }
        if ( project.getTestCompileSourceRoots() != null )
        {
            sourceRoots.addAll( project.getTestCompileSourceRoots() );
        }

        for ( String sourceRoot : sourceRoots )
        {
            final Path sourceRootPath = Paths.get( sourceRoot );
            if ( Files.isDirectory( sourceRootPath )
                            && sourceRootPath.startsWith( targetDir )
                            && !( sourceRootPath.startsWith( generatedSourcesDir )
                                            || sourceRootPath.startsWith( generatedTestSourcesDir ) ) )
            { // dir within target
                attachDirIfNotEmpty( sourceRootPath, targetDir, project );
            }
        }
    }

    private void attachOutputs( MavenProject project ) throws IOException
    {
        final List<String> attachedDirs = cacheConfig.getAttachedOutputs();
        for ( String dir : attachedDirs )
        {
            final Path targetDir = Paths.get( project.getBuild().getDirectory() );
            final Path outputDir = targetDir.resolve( dir );
            attachDirIfNotEmpty( outputDir, targetDir, project );
        }
    }

    private void attachDirIfNotEmpty( Path candidateSubDir, Path parentDir, MavenProject project ) throws IOException
    {
        if ( Files.isDirectory( candidateSubDir ) && hasFiles( candidateSubDir ) )
        {
            final Path relativePath = parentDir.relativize( candidateSubDir );
            final String classifier = pathToClassifier( relativePath );
            zipAndAttachArtifact( project, candidateSubDir, classifier );
            LOGGER.debug( "Attached directory: {}", candidateSubDir );
        }
    }

    private boolean hasFiles( Path candidateSubDir ) throws IOException
    {
        final MutableBoolean hasFiles = new MutableBoolean();
        Files.walkFileTree( candidateSubDir, new SimpleFileVisitor<Path>()
        {

            @Override
            public FileVisitResult visitFile( Path path, BasicFileAttributes basicFileAttributes )
            {
                hasFiles.setTrue();
                return FileVisitResult.TERMINATE;
            }
        } );
        return hasFiles.booleanValue();
    }

    private boolean isOutputArtifact( String name )
    {
        List<Pattern> excludePatterns = cacheConfig.getExcludePatterns();
        for ( Pattern pattern : excludePatterns )
        {
            if ( pattern.matcher( name ).matches() )
            {
                return false;
            }
        }
        return true;
    }
}
