sootup.java.bytecode.inputlocation.JavaModulePathAnalysisInputLocation Maven / Gradle / Ivy
package sootup.java.bytecode.inputlocation;
/*-
* #%L
* Soot - a J*va Optimization Framework
* %%
* Copyright (C) 2018-2020 Andreas Dann, Christian Brüggemann and others
* %%
* 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 2.1 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 com.google.common.base.Preconditions;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.util.Collection;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.Nonnull;
import sootup.core.IdentifierFactory;
import sootup.core.frontend.AbstractClassSource;
import sootup.core.frontend.ClassProvider;
import sootup.core.frontend.SootClassSource;
import sootup.core.inputlocation.AnalysisInputLocation;
import sootup.core.types.ClassType;
import sootup.core.views.View;
import sootup.java.core.JavaModuleIdentifierFactory;
import sootup.java.core.JavaModuleInfo;
import sootup.java.core.JavaSootClass;
import sootup.java.core.ModuleInfoAnalysisInputLocation;
import sootup.java.core.signatures.ModulePackageName;
import sootup.java.core.signatures.ModuleSignature;
import sootup.java.core.types.JavaClassType;
/**
* An implementation of the {@link AnalysisInputLocation} interface for the Java modulepath. Handles
* directories, archives (including wildcard denoted archives) as stated in the official
* documentation:
*
* @author Andreas Dann created on 28.05.18
* @see ModuleFinder
*/
public class JavaModulePathAnalysisInputLocation implements ModuleInfoAnalysisInputLocation {
@Nonnull private final ModuleFinder moduleFinder;
/**
* Creates a {@link JavaModulePathAnalysisInputLocation} which locates classes in the given module
* path.
*
* @param modulePath The class path to search in The {@link ClassProvider} for generating {@link
* SootClassSource}es for the files found on the class path
*/
public JavaModulePathAnalysisInputLocation(@Nonnull String modulePath) {
this(modulePath, FileSystems.getDefault());
}
/**
* Creates a {@link JavaModulePathAnalysisInputLocation} which locates classes in the given module
* path.
*
* @param modulePath The class path to search in The {@link ClassProvider} for generating {@link
* SootClassSource}es for the files found on the class path
* @param fileSystem filesystem for the path
*/
public JavaModulePathAnalysisInputLocation(
@Nonnull String modulePath, @Nonnull FileSystem fileSystem) {
moduleFinder = new ModuleFinder(modulePath, fileSystem);
}
@Nonnull
public Optional getModuleInfo(ModuleSignature sig, View> view) {
return moduleFinder.getModuleInfo(sig);
}
@Nonnull
public Set getModules(View> view) {
return moduleFinder.getModules();
}
@Override
@Nonnull
public Collection extends AbstractClassSource> getClassSources(
@Nonnull View> view) {
IdentifierFactory identifierFactory = view.getIdentifierFactory();
Preconditions.checkArgument(
identifierFactory instanceof JavaModuleIdentifierFactory,
"Factory must be a JavaModuleSignatureFactory");
Collection allModules = moduleFinder.getAllModules();
return allModules.stream()
.flatMap(sig -> getClassSourcesInternal(sig, view))
.collect(Collectors.toList());
}
@Override
@Nonnull
public Collection extends AbstractClassSource> getModulesClassSources(
@Nonnull ModuleSignature moduleSignature, @Nonnull View> view) {
IdentifierFactory identifierFactory = view.getIdentifierFactory();
Preconditions.checkArgument(
identifierFactory instanceof JavaModuleIdentifierFactory,
"Factory must be a JavaModuleSignatureFactory");
return getClassSourcesInternal(moduleSignature, view).collect(Collectors.toList());
}
protected Stream extends AbstractClassSource> getClassSourcesInternal(
@Nonnull ModuleSignature moduleSignature, @Nonnull View> view) {
AnalysisInputLocation inputLocation = moduleFinder.getModule(moduleSignature);
if (inputLocation == null) {
return Stream.empty();
}
return inputLocation.getClassSources(view).stream();
}
@Override
@Nonnull
public Optional extends AbstractClassSource> getClassSource(
@Nonnull ClassType classType, @Nonnull View> view) {
JavaClassType klassType = (JavaClassType) classType;
ModuleSignature modulename =
((ModulePackageName) klassType.getPackageName()).getModuleSignature();
// get inputlocation from cache
AnalysisInputLocation inputLocation = moduleFinder.getModule(modulename);
if (inputLocation == null) {
return Optional.empty();
}
return inputLocation.getClassSource(klassType, view);
}
@Override
public int hashCode() {
return moduleFinder.hashCode();
}
@Override
public boolean equals(Object o) {
if (!(o instanceof JavaModulePathAnalysisInputLocation)) {
return false;
}
return moduleFinder.equals(((JavaModulePathAnalysisInputLocation) o).moduleFinder);
}
}