/******************************************************************************* * Copyright (c) 2016 Red Hat, Inc. * Distributed under license by Red Hat, Inc. All rights reserved. * This program is made available under the terms of the * Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.jboss.tools.windup.core.services; import java.io.File; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.inject.Inject; import javax.inject.Singleton; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.e4.core.di.annotations.Creatable; import org.eclipse.osgi.util.NLS; import org.jboss.tools.windup.core.IWindupListener; import org.jboss.tools.windup.core.WindupCorePlugin; import org.jboss.tools.windup.core.WindupProgressMonitorAdapter; import org.jboss.tools.windup.core.internal.Messages; import org.jboss.tools.windup.core.utils.FileUtils; import org.jboss.tools.windup.model.OptionFacades; import org.jboss.tools.windup.model.OptionFacades.OptionTypeFacade; import org.jboss.tools.windup.model.OptionFacades.OptionsFacadeManager; import org.jboss.tools.windup.model.domain.ModelService; import org.jboss.tools.windup.model.domain.WorkspaceResourceUtils; import org.jboss.tools.windup.runtime.WindupRmiClient; import org.jboss.tools.windup.runtime.WindupRuntimePlugin; import org.jboss.tools.windup.windup.ConfigurationElement; import org.jboss.tools.windup.windup.Input; import org.jboss.tools.windup.windup.MigrationPath; import org.jboss.tools.windup.windup.Pair; import org.jboss.windup.bootstrap.help.OptionDescription; import org.jboss.windup.config.SkipReportsRenderingOption; import org.jboss.windup.exec.configuration.options.SourceOption; import org.jboss.windup.exec.configuration.options.TargetOption; import org.jboss.windup.exec.configuration.options.UserRulesDirectoryOption; import org.jboss.windup.rules.apps.java.config.ScanPackagesOption; import org.jboss.windup.rules.apps.java.config.SourceModeOption; import org.jboss.windup.tooling.ExecutionBuilder; import org.jboss.windup.tooling.ExecutionResults; import org.jboss.windup.tooling.data.Classification; import org.jboss.windup.tooling.data.Hint; import org.jboss.windup.tooling.data.ReportLink; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Multimap; /** * <p> * Service used to perform Windup operations inside of Eclipse. * </p> */ @Singleton @Creatable public class WindupService { private List<IWindupListener> windupListeners = new ArrayList<IWindupListener>(); private Map<IProject, ExecutionResults> projectToResults = new HashMap<>(); @Inject private ModelService modelService; @Inject private WindupRmiClient windupClient; /** * Returns an {@link Iterable} with all {@link Hint}s returned by Windup during the last run. * * NOTE: This will return an empty list if Windup has not yet been run on this project. */ public Iterable<Hint> getHints(IResource resource) { ExecutionResults results = projectToResults.get(resource.getProject()); if (results == null) return Collections.emptyList(); else return results.getHints(); } /** * Returns an {@link Iterable} with all {@link Classification}s returned by Windup during the last run. * * NOTE: This will return an empty list if Windup has not yet been run on this project. */ public Iterable<Classification> getClassifications(IResource resource, IProgressMonitor monitor) { ExecutionResults results = projectToResults.get(resource.getProject()); if (results == null) return Collections.emptyList(); else return results.getClassifications(); } public IStatus generateGraph(ConfigurationElement configuration, IProgressMonitor progress) { progress.subTask(Messages.startingWindup); modelService.synch(configuration); IPath basePath = modelService.getGeneratedReportsBaseLocation(configuration); File baseOutputDir = basePath.toFile(); progress.subTask(Messages.removing_old_report); FileUtils.delete(baseOutputDir, true); IStatus status = null; try { for (Input input : configuration.getInputs()) { ExecutionBuilder execBuilder = windupClient.getExecutionBuilder(); execBuilder.clear(); Path projectPath = WorkspaceResourceUtils.computePath(input.getUri()); progress.beginTask(NLS.bind(Messages.generate_windup_graph_for, input.getName()), IProgressMonitor.UNKNOWN); IPath outputPath = modelService.getGeneratedReportBaseLocation(configuration, input); execBuilder.setWindupHome(WindupRuntimePlugin.findWindupHome().toPath().toString()); execBuilder.setInput(projectPath.toString()); execBuilder.setOutput(outputPath.toFile().toPath().toString()); execBuilder.setProgressMonitor(new WindupProgressMonitorAdapter(progress)); execBuilder.setOption(SourceModeOption.NAME, true); execBuilder.setOption(SkipReportsRenderingOption.NAME, !configuration.isGenerateReport()); execBuilder.ignore("\\.class$"); MigrationPath path = configuration.getMigrationPath(); execBuilder.setOption(TargetOption.NAME, Lists.newArrayList(path.getTarget().getId())); if (path.getSource() != null) { execBuilder.setOption(SourceOption.NAME, Lists.newArrayList(path.getSource().getId())); } if (!configuration.getPackages().isEmpty()) { execBuilder.setOption(ScanPackagesOption.NAME, Lists.newArrayList(configuration.getPackages())); } modelService.cleanCustomRuleRepositories(configuration); if (!configuration.getUserRulesDirectories().isEmpty()) { // TODO: Temporary - see https://tree.taiga.io/project/rdruss-jboss-migration-windup-v3/task/884 File file = new File(configuration.getUserRulesDirectories().get(0)); execBuilder.setOption(UserRulesDirectoryOption.NAME, file); } OptionsFacadeManager facadeMgr = modelService.getOptionFacadeManager(); Multimap<String, String> optionMap = ArrayListMultimap.create(); for (Pair pair : configuration.getOptions()) { String name = pair.getKey(); String value = pair.getValue(); optionMap.put(name, value); } for (String name : optionMap.keySet()) { List<String> values = (List<String>)optionMap.get(name); OptionDescription option = facadeMgr.findOptionDescription(name); OptionTypeFacade<?> typeFacade = facadeMgr.getFacade(option, OptionTypeFacade.class); if (OptionFacades.isSingleValued(option)) { Object optionValue = typeFacade.newInstance(values.get(0)); execBuilder.setOption(name, optionValue); } else { List<?> optionValues = typeFacade.newInstance(values); execBuilder.setOption(name, optionValues); } } WindupCorePlugin.logInfo("WindupService is executing the ExecutionBuilder"); //$NON-NLS-1$ ExecutionResults results = execBuilder.execute(); WindupCorePlugin.logInfo("ExecutionBuilder has returned the Windup results"); //$NON-NLS-1$ modelService.populateConfiguration(configuration, input, outputPath, results); } modelService.save(); status = Status.OK_STATUS; } catch (Exception e) { WindupCorePlugin.log(e); throw new RuntimeException(e); } finally { // mark the monitor as complete progress.done(); } return status; } /** * <p> * Determines if a report exists for the {@link IProject} containing the given {@link IResource}. * </p> * * @param resource determine if a report exists for the {@link IProject} containing this {@link IResource} * * @return <code>true</code> if a report exists for the {@link IProject} containing the given {@link IResource}, <code>false</code> otherwise. */ public boolean reportExists(IResource resource) { IPath reportPath = getProjectReportPath(resource); File reportDir = new File(reportPath.toString()); return reportDir.exists(); } /** * <p> * Get the Windup report for the given resource. * </p> * * @param resource get the location of the Windup report for this {@link IResource} * * @return location of the Windup report for the given {@link IResource} */ public IPath getReportLocation(IResource resource) { IPath projectReportPath = getProjectReportPath(resource); IPath reportPath = null; switch (resource.getType()) { // if selected resource is a file get the file specific report page case IResource.FILE: { File resourceAsFile = resource.getLocation().toFile().getAbsoluteFile(); ExecutionResults executionResults = projectToResults.get(resource.getProject()); if (executionResults == null) break; for (ReportLink reportLink : executionResults.getReportLinks()) { if (resourceAsFile.equals(reportLink.getInputFile())) { File reportFile = reportLink.getReportFile(); Path projectPath = resource.getProject().getLocation().toFile().toPath(); Path reportFileRelativeToProject = projectPath.relativize(reportFile.toPath()); IPath projectLocation = resource.getProject().getLocation(); reportPath = projectLocation.append(reportFileRelativeToProject.toString()); break; } } break; } /* * if selected resource is the project then get the Windup report home page for that project */ case IResource.PROJECT: { reportPath = projectReportPath.append(ModelService.PROJECT_REPORT_HOME_PAGE); break; } default: { break; } } // determine if the report of the given file exists, if it doesn't return null if (reportPath != null) { File reportFile = new File(reportPath.toString()); if (!reportFile.exists()) { reportPath = null; } } return reportPath; } /** * <p> * Get the Windup report parent directory for the given resource. * </p> * * @param resource get the location of the Windup report parent directory for this {@link IResource} * * @return location of the Windup report parent directory for the given {@link IResource} */ public IPath getReportParentDirectoryLocation(IResource resource) { return getProjectReportPath(resource); } /** * <p> * Registers a {@link IWindupListener}. * </p> * * @param listener {@link IWindupListener} to register */ public void addWindupListener(IWindupListener listener) { this.windupListeners.add(listener); } /** * <p> * Removes an already registered {@link IWindupListener}. * </p> * * @param listener {@link IWindupListener} to unregister */ public void removeWindupListener(IWindupListener listener) { this.windupListeners.remove(listener); } /** * <p> * Get the location where the report should be stored for the {@link IProject} containing the given {@link IResource} * </p> * * @param resource get the location where the report should be stored for the {@link IProject} containing this {@link IResource} * * @return location where the report should be stored for the {@link IProject} containing the given {@link IResource} */ private IPath getProjectReportPath(IResource resource) { return ModelService.reportsDir.append(resource.getProject().getName()); } }