package org.jboss.windup.tooling;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.rmi.RemoteException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Handler;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import javax.inject.Inject;
import org.jboss.forge.furnace.Furnace;
import org.jboss.forge.furnace.util.Lists;
import org.jboss.windup.config.SkipReportsRenderingOption;
import org.jboss.windup.config.loader.RuleLoader;
import org.jboss.windup.config.loader.RuleLoaderContext;
import org.jboss.windup.config.metadata.RuleProviderRegistryCache;
import org.jboss.windup.exec.WindupProcessor;
import org.jboss.windup.exec.configuration.WindupConfiguration;
import org.jboss.windup.graph.GraphContext;
import org.jboss.windup.graph.GraphContextFactory;
import org.jboss.windup.graph.model.report.IgnoredFileRegexModel;
import org.jboss.windup.graph.service.GraphService;
import org.jboss.windup.rules.apps.java.config.ExcludePackagesOption;
import org.jboss.windup.rules.apps.java.config.ScanPackagesOption;
import org.jboss.windup.rules.apps.java.config.SourceModeOption;
import org.jboss.windup.rules.apps.java.model.WindupJavaConfigurationModel;
import org.jboss.windup.rules.apps.java.service.WindupJavaConfigurationService;
import org.jboss.windup.tooling.quickfix.QuickfixLocationDTO;
import org.jboss.windup.tooling.quickfix.QuickfixService;
import org.jboss.windup.tooling.rules.RuleProviderRegistry;
import org.jboss.windup.tooling.rules.RuleProviderRegistryImpl;
import org.jboss.windup.util.PathUtil;
import org.jboss.windup.util.exception.WindupException;
/**
* @author <a href="mailto:jesse.sightler@gmail.com">Jesse Sightler</a>
*/
public class ExecutionBuilderImpl implements ExecutionBuilder
{
@Inject
private GraphContextFactory graphContextFactory;
@Inject
private ToolingXMLService toolingXMLService;
@Inject
private WindupProcessor processor;
@Inject
private Furnace furnace;
@Inject
private RuleProviderRegistryCache ruleProviderCache;
private String windupHome;
private WindupToolingProgressMonitor progressMonitor;
private String input;
private String output;
private Set<String> ignorePathPatterns = new HashSet<>();
private Set<String> includePackagePrefixSet = new HashSet<>();
private Set<String> excludePackagePrefixSet = new HashSet<>();
private Set<String> userRulesPathSet = new HashSet<>();
private Map<String, Object> options = new HashMap<>();
private String version;
@Inject
private RuleLoader ruleLoader;
@Inject
private QuickfixService quickfixService;
@Override
public void clear() throws RemoteException
{
this.windupHome = null;
this.progressMonitor = null;
this.input = null;
this.output = null;
this.ignorePathPatterns.clear();
this.includePackagePrefixSet.clear();
this.excludePackagePrefixSet.clear();
this.userRulesPathSet.clear();
this.options.clear();
}
// TODO: Should we also do UnicastRemoteObject.unexportObject(this, true)?
@Override
public void terminate() throws RemoteException
{
furnace.stop();
try
{
Thread.sleep(5000);
}
catch (InterruptedException e)
{
}
Runtime.getRuntime().halt(1);
}
@Override
public void setWindupHome(String windupHome) throws RemoteException
{
this.windupHome = windupHome;
}
@Override
public void setInput(String input) throws RemoteException
{
this.input = input;
}
@Override
public void setOutput(String output) throws RemoteException
{
this.output = output;
}
@Override
public void ignore(String ignorePattern) throws RemoteException
{
this.ignorePathPatterns.add(ignorePattern);
}
@Override
public void includePackage(String packagePrefix) throws RemoteException
{
this.includePackagePrefixSet.add(packagePrefix);
}
@Override
public void includePackages(Collection<String> includePackagePrefixes) throws RemoteException
{
if (includePackagePrefixes != null)
this.includePackagePrefixSet.addAll(includePackagePrefixes);
}
@Override
public void excludePackage(String packagePrefix) throws RemoteException
{
this.excludePackagePrefixSet.add(packagePrefix);
}
@Override
public void excludePackages(Collection<String> excludePackagePrefixes) throws RemoteException
{
if (excludePackagePrefixes != null)
this.excludePackagePrefixSet.addAll(excludePackagePrefixes);
}
@Override
public void setProgressMonitor(WindupToolingProgressMonitor monitor) throws RemoteException
{
this.progressMonitor = monitor;
}
@Override
public void sourceOnlyMode() throws RemoteException
{
options.put(SourceModeOption.NAME, true);
}
@Override
public void skipReportGeneration() throws RemoteException
{
options.put(SkipReportsRenderingOption.NAME, true);
}
@Override
public void addUserRulesPath(String rulesPath) throws RemoteException
{
if (rulesPath == null)
return;
String pathString = Paths.get(rulesPath).normalize().toAbsolutePath().toString();
this.userRulesPathSet.add(pathString);
}
@Override
public void addUserRulesPaths(Iterable<String> rulesPaths) throws RemoteException
{
if (rulesPaths == null)
return;
for (String rulesPath : rulesPaths)
{
this.addUserRulesPath(rulesPath);
}
}
@Override
public void setOption(String name, Object value) throws RemoteException
{
this.options.put(name, value);
}
@Override
public String getVersion() throws RemoteException
{
return version;
}
@Override
public void setVersion(String version) throws RemoteException
{
this.version = version;
}
public String transform(String transformationID, QuickfixLocationDTO locationDTO) throws RemoteException
{
return quickfixService.transform(transformationID, locationDTO);
}
@Override
public ExecutionResults execute() throws RemoteException
{
PathUtil.setWindupHome(Paths.get(this.windupHome));
WindupConfiguration windupConfiguration = new WindupConfiguration();
try
{
windupConfiguration.useDefaultDirectories();
}
catch (IOException e)
{
throw new WindupException("Failed to configure windup due to: " + e.getMessage(), e);
}
ToolingProgressMonitorAdapter progressMonitorAdapter = new ToolingProgressMonitorAdapter(this.progressMonitor);
windupConfiguration.addInputPath(Paths.get(this.input));
windupConfiguration.setOutputDirectory(Paths.get(this.output));
windupConfiguration.setProgressMonitor(progressMonitorAdapter);
Path graphPath = Paths.get(output).resolve(GraphContextFactory.DEFAULT_GRAPH_SUBDIRECTORY);
Logger globalLogger = Logger.getLogger("");
WindupProgressLoggingHandler loggingHandler = null;
if (progressMonitor instanceof WindupToolingProgressMonitor)
{
loggingHandler = new WindupProgressLoggingHandler((WindupToolingProgressMonitor) progressMonitor);
globalLogger.addHandler(loggingHandler);
}
try (final GraphContext graphContext = graphContextFactory.create(graphPath))
{
GraphService<IgnoredFileRegexModel> graphService = new GraphService<>(graphContext, IgnoredFileRegexModel.class);
for (String ignorePattern : this.ignorePathPatterns)
{
IgnoredFileRegexModel ignored = graphService.create();
ignored.setRegex(ignorePattern);
WindupJavaConfigurationModel javaCfg = WindupJavaConfigurationService.getJavaConfigurationModel(graphContext);
javaCfg.addIgnoredFileRegex(ignored);
}
windupConfiguration.setOptionValue(ScanPackagesOption.NAME, Lists.toList(this.includePackagePrefixSet));
windupConfiguration.setOptionValue(ExcludePackagesOption.NAME, Lists.toList(this.excludePackagePrefixSet));
for (Map.Entry<String, Object> option : options.entrySet())
{
windupConfiguration.setOptionValue(option.getKey(), option.getValue());
}
windupConfiguration.setGraphContext(graphContext);
processor.execute(windupConfiguration);
return new ExecutionResultsImpl(graphContext, toolingXMLService);
}
catch (IOException e)
{
throw new WindupException("Failed to instantiate graph due to: " + e.getMessage(), e);
}
finally
{
if (loggingHandler != null)
globalLogger.removeHandler(loggingHandler);
}
}
@Override
public RuleProviderRegistry getRuleProviderRegistry(List<String> pathStrings) throws RemoteException
{
RuleProviderRegistryImpl ruleProviderRegistry = new RuleProviderRegistryImpl();
List<Path> paths = pathStrings.stream().map(pathString -> Paths.get(pathString)).collect(Collectors.toList());
RuleLoaderContext ruleLoaderContext = new RuleLoaderContext(paths, null);
org.jboss.windup.config.metadata.RuleProviderRegistry registry = this.ruleLoader.loadConfiguration(ruleLoaderContext);
ruleProviderRegistry.buildRuleProviders(registry);
return ruleProviderRegistry;
}
@Override
public RuleProviderRegistry getSystemRuleProviderRegistry() throws RemoteException
{
RuleProviderRegistryImpl ruleProviderRegistry = new RuleProviderRegistryImpl();
ruleProviderRegistry.buildRuleProviders(ruleProviderCache.getRuleProviderRegistry());
return ruleProviderRegistry;
}
private class WindupProgressLoggingHandler extends Handler
{
private final WindupToolingProgressMonitor monitor;
public WindupProgressLoggingHandler(WindupToolingProgressMonitor monitor)
{
this.monitor = monitor;
}
@Override
public void publish(LogRecord record)
{
if (this.monitor == null)
return;
try
{
this.monitor.logMessage(record);
}
catch (RemoteException e)
{
}
}
@Override
public void flush()
{
}
@Override
public void close() throws SecurityException
{
}
}
}