package org.jboss.windup.config.projecttraversal; import org.jboss.windup.config.AbstractRuleLifecycleListener; import org.jboss.windup.config.GraphRewrite; import org.jboss.windup.graph.GraphContext; import org.jboss.windup.graph.model.ProjectModel; import org.jboss.windup.graph.model.WindupConfigurationModel; import org.jboss.windup.graph.model.resource.FileModel; import org.jboss.windup.graph.service.WindupConfigurationService; import org.jboss.windup.graph.traversal.ProjectModelTraversal; import java.lang.ref.SoftReference; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; /** * Maintains a cache of some traversal data to prevent the need for frequent recalculation of this data. * * @author <a href="mailto:jesse.sightler@gmail.com">Jesse Sightler</a> */ public class ProjectTraversalCache extends AbstractRuleLifecycleListener { private static final Map<ProjectModel, SoftReference<Set<ProjectModel>>> projectToApplicationCache = new ConcurrentHashMap<>(); @Override public void beforeExecution(GraphRewrite event) { projectToApplicationCache.clear(); } public static Set<ProjectModel> getApplicationsForProject(GraphContext context, ProjectModel project) { Set<ProjectModel> results = getFromCache(project); if (results != null) return results; results = new HashSet<>(); WindupConfigurationModel configurationModel = WindupConfigurationService.getConfigurationModel(context); for (FileModel inputFile : configurationModel.getInputPaths()) { ProjectModel application = inputFile.getProjectModel(); ProjectModelTraversal traversal = new ProjectModelTraversal(application); Set<ProjectModel> projectsInApplication = traversal.getAllProjects(true); if (projectsInApplication.contains(project)) results.add(application); } /* * HACK -- In tests it is possible for there to be no true "application". This can result * in no results for this particular project. * * In a case like this, the best that we can do is to simply return the project itself as the Set. */ if (results.isEmpty()) results.add(project); putInCache(project, results); return results; } private static Set<ProjectModel> getFromCache(ProjectModel project) { if (project == null) return null; synchronized (projectToApplicationCache) { SoftReference<Set<ProjectModel>> referenceProjectsSet = projectToApplicationCache.get(project); return referenceProjectsSet == null ? null : referenceProjectsSet.get(); } } private static void putInCache(ProjectModel project, Set<ProjectModel> projects) { if (project == null) return; synchronized (projectToApplicationCache) { SoftReference<Set<ProjectModel>> referenceProjectsSet = new SoftReference<>(projects); projectToApplicationCache.put(project, referenceProjectsSet); } } }