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

org.apache.maven.shared.dependency.analyzer.ProjectDependencyAnalysis Maven / Gradle / Ivy

The newest version!
/*
 * 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.shared.dependency.analyzer;

import java.util.Arrays;
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.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.maven.artifact.Artifact;

/**
 * Project dependencies analysis result.
 *
 * @author Mark Hobson
 */
public class ProjectDependencyAnalysis {
    // fields -----------------------------------------------------------------

    private final Map> usedDeclaredArtifacts;

    private final Map> usedUndeclaredArtifacts;

    private final Set unusedDeclaredArtifacts;

    private final Set testArtifactsWithNonTestScope;

    /**
     * 

Constructor for ProjectDependencyAnalysis.

*/ public ProjectDependencyAnalysis() { this(null, (Map>) null, null, null); } /** *

Constructor for ProjectDependencyAnalysis to maintain compatibility with old API

* * @param usedDeclaredArtifacts artifacts both used and declared * @param usedUndeclaredArtifacts artifacts used but not declared * @param unusedDeclaredArtifacts artifacts declared but not used */ public ProjectDependencyAnalysis( Set usedDeclaredArtifacts, Set usedUndeclaredArtifacts, Set unusedDeclaredArtifacts) { this(usedDeclaredArtifacts, usedUndeclaredArtifacts, unusedDeclaredArtifacts, Collections.emptySet()); } /** *

Constructor for ProjectDependencyAnalysis.

* * @param usedDeclaredArtifacts artifacts both used and declared * @param usedUndeclaredArtifacts artifacts used but not declared * @param unusedDeclaredArtifacts artifacts declared but not used * @param testArtifactsWithNonTestScope artifacts only used in tests but not declared with test scope */ public ProjectDependencyAnalysis( Set usedDeclaredArtifacts, Set usedUndeclaredArtifacts, Set unusedDeclaredArtifacts, Set testArtifactsWithNonTestScope) { this( mapWithKeys(usedDeclaredArtifacts), mapWithKeys(usedUndeclaredArtifacts), unusedDeclaredArtifacts, testArtifactsWithNonTestScope); } public ProjectDependencyAnalysis( Map> usedDeclaredArtifacts, Map> usedUndeclaredArtifacts, Set unusedDeclaredArtifacts, Set testArtifactsWithNonTestScope) { this.usedDeclaredArtifacts = safeCopy(usedDeclaredArtifacts); this.usedUndeclaredArtifacts = safeCopy(usedUndeclaredArtifacts); this.unusedDeclaredArtifacts = safeCopy(unusedDeclaredArtifacts); this.testArtifactsWithNonTestScope = safeCopy(testArtifactsWithNonTestScope); } /** * Returns artifacts both used and declared. * * @return artifacts both used and declared */ public Set getUsedDeclaredArtifacts() { return safeCopy(usedDeclaredArtifacts.keySet()); } /** * Returns artifacts both used and declared. * * @return artifacts both used and declared */ public Map> getUsedDeclaredArtifactsWithUsages() { return safeCopy(usedDeclaredArtifacts); } /** * Returns artifacts used but not declared. * * @return artifacts used but not declared */ public Set getUsedUndeclaredArtifacts() { return safeCopy(usedUndeclaredArtifacts.keySet()); } /** * Returns artifacts used but not declared. * * @return artifacts used but not declared */ public Map> getUsedUndeclaredArtifactsWithClasses() { Map> usedUndeclaredArtifactsWithClasses = new HashMap<>(); for (Map.Entry> entry : usedUndeclaredArtifacts.entrySet()) { usedUndeclaredArtifactsWithClasses.put( entry.getKey(), entry.getValue().stream() .map(DependencyUsage::getDependencyClass) .collect(Collectors.toSet())); } return usedUndeclaredArtifactsWithClasses; } public Map> getUsedUndeclaredArtifactsWithUsages() { return safeCopy(usedUndeclaredArtifacts); } /** * Returns artifacts declared but not used. * * @return artifacts declared but not used */ public Set getUnusedDeclaredArtifacts() { return safeCopy(unusedDeclaredArtifacts); } /** * Returns artifacts only used in tests but not declared with test scope. * * @return artifacts only used in tests but not declared with test scope */ public Set getTestArtifactsWithNonTestScope() { return safeCopy(testArtifactsWithNonTestScope); } /** * Filter non-compile scoped artifacts from unused declared. * * @return updated project dependency analysis * @since 1.3 */ public ProjectDependencyAnalysis ignoreNonCompile() { Set filteredUnusedDeclared = new HashSet<>(unusedDeclaredArtifacts); filteredUnusedDeclared.removeIf(artifact -> !artifact.getScope().equals(Artifact.SCOPE_COMPILE)); return new ProjectDependencyAnalysis( usedDeclaredArtifacts, usedUndeclaredArtifacts, filteredUnusedDeclared, testArtifactsWithNonTestScope); } /** * Force use status of some declared dependencies, to manually fix consequences of bytecode-level analysis which * happens to not detect some effective use (constants, annotation with source-retention, javadoc). * * @param forceUsedDependencies dependencies to move from "unused-declared" to "used-declared", with * groupId:artifactId format * @return updated project dependency analysis * @throws ProjectDependencyAnalyzerException if dependencies forced were either not declared or already detected as * used * @since 1.3 */ @SuppressWarnings("UnusedReturnValue") public ProjectDependencyAnalysis forceDeclaredDependenciesUsage(String[] forceUsedDependencies) throws ProjectDependencyAnalyzerException { Set forced = new HashSet<>(Arrays.asList(forceUsedDependencies)); Set forcedUnusedDeclared = new HashSet<>(unusedDeclaredArtifacts); Set forcedUsedDeclared = new HashSet<>(usedDeclaredArtifacts.keySet()); Iterator iter = forcedUnusedDeclared.iterator(); while (iter.hasNext()) { Artifact artifact = iter.next(); if (forced.remove(artifact.getGroupId() + ':' + artifact.getArtifactId())) { // ok, change artifact status from unused-declared to used-declared iter.remove(); forcedUsedDeclared.add(artifact); } } if (!forced.isEmpty()) { // trying to force dependencies as used-declared which were not declared or already detected as used Set used = new HashSet<>(); for (Artifact artifact : usedDeclaredArtifacts.keySet()) { String id = artifact.getGroupId() + ':' + artifact.getArtifactId(); if (forced.remove(id)) { used.add(id); } } StringBuilder builder = new StringBuilder(); if (!forced.isEmpty()) { builder.append("not declared: ").append(forced); } if (!used.isEmpty()) { if (builder.length() > 0) { builder.append(" and "); } builder.append("declared but already detected as used: ").append(used); } throw new ProjectDependencyAnalyzerException("Trying to force use of dependencies which are " + builder); } return new ProjectDependencyAnalysis( mapWithKeys(forcedUsedDeclared), usedUndeclaredArtifacts, forcedUnusedDeclared, testArtifactsWithNonTestScope); } /** *

hashCode.

* * @return an int */ @Override public int hashCode() { int hashCode = getUsedDeclaredArtifacts().hashCode(); hashCode = (hashCode * 37) + getUsedUndeclaredArtifacts().hashCode(); hashCode = (hashCode * 37) + getUnusedDeclaredArtifacts().hashCode(); hashCode = (hashCode * 37) + getTestArtifactsWithNonTestScope().hashCode(); return hashCode; } /** {@inheritDoc} */ @Override public boolean equals(Object object) { if (object instanceof ProjectDependencyAnalysis) { ProjectDependencyAnalysis analysis = (ProjectDependencyAnalysis) object; return getUsedDeclaredArtifacts().equals(analysis.getUsedDeclaredArtifacts()) && getUsedUndeclaredArtifacts().equals(analysis.getUsedUndeclaredArtifacts()) && getUnusedDeclaredArtifacts().equals(analysis.getUnusedDeclaredArtifacts()) && getTestArtifactsWithNonTestScope().equals(analysis.getTestArtifactsWithNonTestScope()); } return false; } /** *

toString.

* * @return a {@link java.lang.String} object. */ @Override public String toString() { StringBuilder buffer = new StringBuilder(); if (!getUsedDeclaredArtifacts().isEmpty()) { buffer.append("usedDeclaredArtifacts=").append(getUsedDeclaredArtifacts()); } if (!getUsedUndeclaredArtifacts().isEmpty()) { if (buffer.length() > 0) { buffer.append(","); } buffer.append("usedUndeclaredArtifacts=").append(getUsedUndeclaredArtifacts()); } if (!getUnusedDeclaredArtifacts().isEmpty()) { if (buffer.length() > 0) { buffer.append(","); } buffer.append("unusedDeclaredArtifacts=").append(getUnusedDeclaredArtifacts()); } if (!getTestArtifactsWithNonTestScope().isEmpty()) { if (buffer.length() > 0) { buffer.append(","); } buffer.append("testArtifactsWithNonTestScope=").append(getTestArtifactsWithNonTestScope()); } buffer.insert(0, "["); buffer.insert(0, getClass().getName()); buffer.append("]"); return buffer.toString(); } // private methods -------------------------------------------------------- private Set safeCopy(Set set) { return (set == null) ? Collections.emptySet() : Collections.unmodifiableSet(new LinkedHashSet<>(set)); } private static Map> safeCopy(Map> origMap) { if (origMap == null) { return Collections.emptyMap(); } Map> map = new LinkedHashMap<>(); for (Map.Entry> e : origMap.entrySet()) { map.put(e.getKey(), Collections.unmodifiableSet(new LinkedHashSet<>(e.getValue()))); } return map; } private static Map> mapWithKeys(Set keys) { if (keys == null) { return Collections.emptyMap(); } Map> map = new LinkedHashMap<>(); for (Artifact k : keys) { map.put(k, Collections.emptySet()); } return map; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy