package ru.yandex.qatools.allure.command; import ch.qos.cal10n.MessageConveyor; import io.airlift.command.Option; import io.airlift.command.OptionType; import org.apache.commons.io.FileUtils; import org.apache.log4j.Level; import org.apache.log4j.LogManager; import org.slf4j.cal10n.LocLogger; import org.slf4j.cal10n.LocLoggerFactory; import ru.yandex.qatools.allure.ExitCode; import ru.yandex.qatools.allure.config.Config; import ru.yandex.qatools.allure.logging.Messages; import javax.xml.bind.JAXB; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Collections; import java.util.Locale; import static ru.yandex.qatools.allure.config.ConfigBuilder.newConfig; /** * @author eroshenkoam@yandex-team.ru */ public abstract class AbstractCommand implements AllureCommand { public static final String HOME_DIR_NAME = ".allure"; public static final String BUNDLES_DIR_NAME = "bundles"; public static final String CONFIG_FILE_NAME = "config.xml"; public static final String EXECUTABLE_FILE_NAME = "allure-bundle.jar"; protected final Path homeDirectory = Paths.get(FileUtils.getUserDirectoryPath()).resolve(HOME_DIR_NAME); protected final Path bundlesDirectory = getHomeDirectory().resolve(BUNDLES_DIR_NAME); protected final Path configPath = getHomeDirectory().resolve(CONFIG_FILE_NAME); protected ExitCode exitCode = ExitCode.NO_ERROR; protected Config config; @Option(name = {"-v", "--verbose"}, type = OptionType.GLOBAL, description = "Switch on the verbose mode.") protected boolean verbose = false; @Option(name = {"-q", "--quiet"}, type = OptionType.GLOBAL, description = "Switch on the quiet mode.") protected boolean quiet = false; /** * Run command and handle exceptions if any occurs. See {@link #runUnsafe()} * <p/> * {@inheritDoc} */ @Override public final void run() { setUpLogLevel(); try { init(); runUnsafe(); } catch (IOException | AllureCommandException e) { getLogger().error(Messages.COMMAND_ALLURE_COMMAND_ABORTED, e); setExitCode(ExitCode.GENERIC_ERROR); } } /** * Initialization method. Creates the directories needed during report * report generation and reads client configuration. * * @throws Exception if any occurs. */ protected void init() throws IOException { Files.createDirectories(getHomeDirectory()); Files.createDirectories(getBundlesDirectory()); if (Files.notExists(getConfigPath())) { Path configFile = Files.createFile(getConfigPath()); JAXB.marshal(newConfig(), configFile.toFile()); } config = JAXB.unmarshal(getConfigPath().toFile(), Config.class); } /** * Run command. * * @throws Exception if any occurs. */ protected abstract void runUnsafe() throws IOException, AllureCommandException; /** * Marshall {@link #config} to its file. */ protected synchronized void saveConfig() { Collections.sort(getConfig().getInstalledVersions(), Collections.reverseOrder()); JAXB.marshal(getConfig(), getConfigPath().toFile()); } /** * Create the instance of localized logger. */ protected LocLogger getLogger() { Locale locale = getLocale(); MessageConveyor conveyor = new MessageConveyor(locale); LocLoggerFactory factory = new LocLoggerFactory(conveyor); return factory.getLocLogger(getClass()); } /** * Returns the path to the bundle directory with specified version. */ protected Path getBundlesPath(String version) { return getBundlesDirectory().resolve(version); } /** * Returns the path to the allure-bundle.jar with specified version. */ protected Path getExecutablePath(String version) { return getBundlesPath(version).resolve(EXECUTABLE_FILE_NAME).toAbsolutePath(); } /** * Get the locale form config. If locale is not set use {@link Locale#ENGLISH}. */ protected Locale getLocale() { return config.getLocale() != null ? Locale.forLanguageTag(config.getLocale()) : Locale.ENGLISH; } /** * Get log level depends on provided client parameters such as verbose and quiet. */ protected Level getLogLevel() { return isQuiet() ? Level.OFF : isVerbose() ? Level.DEBUG : Level.INFO; } /** * Configure logger with needed level {@link #getLogLevel()}. */ private void setUpLogLevel() { LogManager.getRootLogger().setLevel(getLogLevel()); } @Override public ExitCode getExitCode() { return exitCode; } public void setExitCode(ExitCode exitCode) { this.exitCode = exitCode; } public Config getConfig() { return config; } public boolean isVerbose() { return verbose; } public boolean isQuiet() { return quiet; } public Path getHomeDirectory() { return homeDirectory; } public Path getBundlesDirectory() { return bundlesDirectory; } public Path getConfigPath() { return configPath; } }