/* * Copyright 2012 Red Hat, Inc. and/or its affiliates. * * Licensed under the Eclipse Public License version 1.0, available at * http://www.eclipse.org/legal/epl-v10.html */ package org.jboss.windup.bootstrap; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicBoolean; import org.apache.commons.lang3.StringUtils; import org.jboss.forge.furnace.Furnace; import org.jboss.forge.furnace.impl.addons.AddonRepositoryImpl; import org.jboss.forge.furnace.repositories.AddonRepository; import org.jboss.forge.furnace.repositories.AddonRepositoryMode; import org.jboss.forge.furnace.repositories.MutableAddonRepository; import org.jboss.forge.furnace.se.FurnaceFactory; import org.jboss.forge.furnace.versions.EmptyVersion; import org.jboss.forge.furnace.versions.SingleVersion; import org.jboss.forge.furnace.versions.Version; import org.jboss.windup.bootstrap.commands.Command; import org.jboss.windup.bootstrap.commands.CommandPhase; import org.jboss.windup.bootstrap.commands.CommandResult; import org.jboss.windup.bootstrap.commands.FurnaceDependent; import org.jboss.windup.bootstrap.commands.addons.AddAddonDirectoryCommand; import org.jboss.windup.bootstrap.commands.addons.AddImmutableAddonDirectoryCommand; import org.jboss.windup.bootstrap.commands.addons.InstallAddonCommand; import org.jboss.windup.bootstrap.commands.addons.ListAddonsCommand; import org.jboss.windup.bootstrap.commands.addons.RemoveAddonCommand; import org.jboss.windup.bootstrap.commands.windup.DiscoverPackagesCommand; import org.jboss.windup.bootstrap.commands.windup.DisplayHelpCommand; import org.jboss.windup.bootstrap.commands.windup.DisplayVersionCommand; import org.jboss.windup.bootstrap.commands.windup.GenerateCompletionDataCommand; import org.jboss.windup.bootstrap.commands.windup.GenerateHelpCacheCommand; import org.jboss.windup.bootstrap.commands.windup.ListSourceTechnologiesCommand; import org.jboss.windup.bootstrap.commands.windup.ListTagsCommand; import org.jboss.windup.bootstrap.commands.windup.ListTargetTechnologiesCommand; import org.jboss.windup.bootstrap.commands.windup.RunWindupCommand; import org.jboss.windup.bootstrap.commands.windup.ServerModeCommand; import org.jboss.windup.bootstrap.commands.windup.UpdateRulesetsCommand; import org.jboss.windup.bootstrap.listener.GreetingListener; /** * A class with a main method to bootstrap Windup. * * @author <a href="mailto:mbriskar@gmail.com">Matej Briskar</a> * @author <a href="mailto:ggastald@redhat.com">George Gastaldi</a> * @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a> */ public class Bootstrap { public static final String WINDUP_HOME = "windup.home"; private final AtomicBoolean batchMode = new AtomicBoolean(false); private Furnace furnace; public static void main(final String[] args) { final List<String> bootstrapArgs = new ArrayList<>(); for (String arg : args) { if (!handleAsSystemProperty(arg)) bootstrapArgs.add(arg); } File rulesDir = getUserRulesDir(); if (!rulesDir.exists()) { rulesDir.mkdirs(); } final String defaultLog = new File(getUserWindupDir(), "log/rhamt.log").getAbsolutePath(); final String logDir = System.getProperty("org.jboss.forge.log.file", defaultLog); System.setProperty("org.jboss.forge.log.file", logDir); final String logManagerName = getServiceName(Bootstrap.class.getClassLoader(), "java.util.logging.LogManager"); if (logManagerName != null) { System.setProperty("java.util.logging.manager", logManagerName); } Bootstrap bootstrap = new Bootstrap(); if (!bootstrap.serverMode(bootstrapArgs)) { bootstrap.run(bootstrapArgs); bootstrap.stop(); } } private static boolean handleAsSystemProperty(String argument) { if (!argument.startsWith("-D")) return false; final String name; final String value; final int index = argument.indexOf('='); if (index == -1) { name = argument.substring(2); value = "true"; } else { name = argument.substring(2, index); value = argument.substring(index + 1); } System.setProperty(name, value); return true; } private static boolean containsMutableRepository(List<AddonRepository> repositories) { boolean result = false; for (AddonRepository repository : repositories) { if (repository instanceof MutableAddonRepository) { result = true; break; } } return result; } public static String promptForListItem(String message, Collection<String> items, String defaultValue) { while (true) { List<String> sorted = new ArrayList<>(items); Collections.sort(sorted); System.out.println(); System.out.println(message); for (String item : sorted) { System.out.println("\t" + item); } String promptMessage = "Please enter the item you would like to choose[" + defaultValue + "]: "; String item = System.console().readLine(promptMessage).trim(); if (StringUtils.isNotBlank(item)) return item; else if (StringUtils.isNotBlank(defaultValue)) return defaultValue; else System.out.println("A selection is required. Please select one of the available items."); } } public static boolean prompt(String message, boolean defaultValue, boolean batchMode) { if (batchMode) { return defaultValue; } else { String defaultMessage = defaultValue ? " [Y,n] " : " [y,N] "; String line = System.console().readLine(message + defaultMessage).trim(); if ("y".equalsIgnoreCase(line)) return true; if ("n".equalsIgnoreCase(line)) return false; return defaultValue; } } private static String getServiceName(final ClassLoader classLoader, final String className) { try (final InputStream stream = classLoader.getResourceAsStream("META-INF/services/" + className)) { if (stream == null) return null; try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) { String line; while ((line = reader.readLine()) != null) { /* * Ignore comments in the file. */ final int i = line.indexOf('#'); if (i != -1) line = line.substring(0, i); line = line.trim(); if (line.length() == 0) continue; return line; } } } catch (IOException e) { // ignore } return null; } public static String getVersion() { return getRuntimeAPIVersion().toString(); } public static String getVersionString() { return "> JBoss Windup, version " + getRuntimeAPIVersion() + ". JBoss Forge, version " + AddonRepositoryImpl.getRuntimeAPIVersion(); } public static Version getRuntimeAPIVersion() { String version = Bootstrap.class.getPackage().getImplementationVersion(); if (version != null) { return new SingleVersion(version); } return EmptyVersion.getInstance(); } private static File getUserRulesDir() { return new File(getUserWindupDir(), "rules"); } public static File getUserWindupDir() { String userHome = System.getProperty("user.home"); if (userHome == null) { Path path = new File("").toPath(); return path.toFile(); } return Paths.get(userHome).resolve(".rhamt").toFile(); } private static File getUserAddonsDir() { return getUserWindupDir().toPath().resolve(".addons").toFile(); } private boolean serverMode(List<String> arguments) { if (ServerModeCommand.isServerMode(arguments)) { ServerModeCommand serverCommand = new ServerModeCommand(arguments); serverCommand.execute(); return true; } return false; } private void run(List<String> args) { try { furnace = FurnaceFactory.getInstance(); furnace.setServerMode(true); CopyOnWriteArrayList<Command> commands = new CopyOnWriteArrayList<>(processArguments(args)); if (!executePhase(CommandPhase.PRE_CONFIGURATION, commands)) return; if (!executePhase(CommandPhase.CONFIGURATION, commands)) return; if (commands.isEmpty()) { // no commands are available, just print the help and exit new DisplayHelpCommand().execute(); return; } if (!containsMutableRepository(furnace.getRepositories())) { furnace.addRepository(AddonRepositoryMode.MUTABLE, getUserAddonsDir()); } if (!executePhase(CommandPhase.POST_CONFIGURATION, commands) || commands.isEmpty()) return; try { Future<Furnace> future = furnace.startAsync(); future.get(); // use future.get() to wait until it is started } catch (Exception e) { System.out.println("Failed to start Windup!"); if (e.getMessage() != null) System.out.println("Failure reason: " + e.getMessage()); e.printStackTrace(); } if (!executePhase(CommandPhase.PRE_EXECUTION, commands) || commands.isEmpty()) return; furnace.addContainerLifecycleListener(new GreetingListener()); if (!executePhase(CommandPhase.EXECUTION, commands) || commands.isEmpty()) return; if (!executePhase(CommandPhase.POST_EXECUTION, commands) || commands.isEmpty()) return; } catch (Throwable t) { System.err.println("Windup execution failed due to: " + t.getMessage()); t.printStackTrace(); } } private void stop() { if (furnace != null && !furnace.getStatus().isStopped()) furnace.stop(); } private List<Command> processArguments(List<String> arguments) { List<String> unknownArgs = new ArrayList<>(); List<Command> commands = new ArrayList<>(); boolean versionCommandAdded = false; for (int i = 0; i < arguments.size(); i++) { final String arg = arguments.get(i); if ("--batchMode".equals(arg) || "-b".equals(arg)) { batchMode.set(true); } else if ("--debug".equals(arg) || "-d".equals(arg)) { /* * This is to avoid the "Unknown option: --debug" message generated by Windup when it receives an option it doesn't understand. */ } else if (arg.equals("-help") || arg.equals("--help") || arg.equals("-h") || arg.equals("/?") || arg.equals("/help")) { commands.add(new DisplayHelpCommand()); } else if ("--install".equals(arg) || "-i".equals(arg)) { commands.add(new InstallAddonCommand(arguments.get(++i), batchMode)); } else if ("--remove".equals(arg) || "-r".equals(arg)) { commands.add(new RemoveAddonCommand(arguments.get(++i), batchMode)); } else if ("--list".equals(arg) || "-l".equals(arg)) { commands.add(new ListAddonsCommand()); } else if ("--addonDir".equals(arg) || "-a".equals(arg)) { commands.add(new AddAddonDirectoryCommand(arguments.get(++i))); } else if ("--immutableAddonDir".equals(arg) || "-m".equals(arg)) { commands.add(new AddImmutableAddonDirectoryCommand(arguments.get(++i))); } else if ("--version".equals(arg) || "-v".equals(arg)) { versionCommandAdded = true; commands.add(new DisplayVersionCommand()); } else if ("--listTags".equals(arg)) { commands.add(new ListTagsCommand()); } else if ("--listSourceTechnologies".equals(arg)) { commands.add(new ListSourceTechnologiesCommand()); } else if ("--listTargetTechnologies".equals(arg)) { commands.add(new ListTargetTechnologiesCommand()); } else if ("--generateCompletionData".equals(arg)) { commands.add(new GenerateCompletionDataCommand(true)); } else if (arg.equals("--generateHelp")) { commands.add(new GenerateHelpCacheCommand()); } else if ("--generateCaches".equals(arg)) { commands.add(new GenerateCompletionDataCommand(true)); commands.add(new GenerateHelpCacheCommand()); } else if ("--discoverPackages".equals(arg)) { unknownArgs.add(arg); commands.add(new DiscoverPackagesCommand(unknownArgs)); } else if (arg.startsWith("--updateRules")) { commands.add(new UpdateRulesetsCommand()); } else { unknownArgs.add(arg); } } if (!versionCommandAdded) commands.add(0, new DisplayVersionCommand(CommandResult.CONTINUE)); List<String> windupArguments = new ArrayList<>(unknownArgs); if (!windupArguments.isEmpty()) { // go ahead and regenerate this every time just in case there are user-added addons that affect the result commands.add(new GenerateHelpCacheCommand()); commands.add(new GenerateCompletionDataCommand(true)); commands.add(new RunWindupCommand(windupArguments, batchMode)); } return commands; } private boolean executePhase(CommandPhase phase, CopyOnWriteArrayList<Command> commands) { for (Command command : commands) { if (phase.equals(command.getPhase())) { commands.remove(command); if (command instanceof FurnaceDependent) ((FurnaceDependent) command).setFurnace(furnace); CommandResult result = command.execute(); if (CommandResult.EXIT.equals(result)) return false; } } return true; } private File getWindupAddonsDir() { return new File(getWindupHome(), "addons"); } private File getWindupHome() { String windupHome = System.getProperty(WINDUP_HOME); if (windupHome == null) { Path path = new File("").toPath(); return path.toFile(); } return Paths.get(windupHome).toFile(); } }