org.nuiton.jaxx.runtime.application.ApplicationBootInitializerSupport Maven / Gradle / Ivy
The newest version!
package org.nuiton.jaxx.runtime.application;
/*-
* #%L
* JAXX :: Runtime
* %%
* Copyright (C) 2008 - 2024 Code Lutin, Ultreia.io
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import io.ultreia.java4all.i18n.I18n;
import io.ultreia.java4all.i18n.runtime.I18nConfiguration;
import io.ultreia.java4all.i18n.runtime.I18nLanguageProvider;
import io.ultreia.java4all.i18n.runtime.boot.DefaultI18nBootLoader;
import io.ultreia.java4all.i18n.runtime.boot.UserI18nBootLoader;
import io.ultreia.java4all.lang.Strings;
import io.ultreia.java4all.util.Zips;
import org.apache.commons.io.FileUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.config.ConfigurationSource;
import org.apache.logging.log4j.core.config.Configurator;
import org.nuiton.jaxx.runtime.application.action.ActionExecutor;
import org.nuiton.jaxx.runtime.application.action.event.WizardActionWorkerExecutorListener;
import org.nuiton.jaxx.runtime.resources.UIResourcesProviders;
import org.nuiton.jaxx.runtime.swing.SwingUtil;
import java.awt.GraphicsEnvironment;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
/**
* Created by tchemit on 31/01/2018.
*
* @author Tony Chemit - [email protected]
*/
public abstract class ApplicationBootInitializerSupport> implements ApplicationBootInitializer {
private static final String I18N_ARCHIVE = "/i18n.zip";
private final String[] args;
private final ImmutableList modules;
private final ApplicationResourceManager resourceManager;
private String LOG_CONFIGURATION_FILE = "/${application.id}-log4j.properties";
private Logger log = LogManager.getLogger(ApplicationBootInitializerSupport.class);
protected ApplicationBootInitializerSupport(String... args) {
log.info(String.format("%s Create boot at %s with arguments: %s (%s)", ApplicationBoot.BOOT_LOG_PREFIX, new Date(), Arrays.toString(args), this));
this.args = args;
this.modules = ModuleInitializer.loadInitializer();
this.resourceManager = new ApplicationResourceManager();
}
@Override
public final String[] getArgs() {
return args;
}
@Override
public boolean haltOnExit() {
return true;
}
@Override
public final ActionExecutor createExecutor(ApplicationBoot boot, Config configuration, Context context) {
log.info(String.format("%s Create executor (boot %s, configuration: %s, context: %s)", ApplicationBoot.BOOT_LOG_PREFIX, boot, configuration, context));
ActionExecutor executor = new ActionExecutor(boot, context);
executor.addActionExecutorListener(new WizardActionWorkerExecutorListener());
return executor;
}
@Override
public final void start(Config config, Context context) {
log.info(String.format("%s Start application (version: %s) at %s (arguments: %s)", ApplicationBoot.BOOT_LOG_PREFIX, config.getApplicationVersion(), new Date(), Arrays.toString(args)));
try {
config.get().doAction(0);
} catch (IllegalAccessException | InvocationTargetException | InstantiationException e) {
throw new RuntimeException("Can't execute command line actions", e);
}
}
@Override
public final void initOnce() throws ApplicationBootInitializerException {
modules.forEach(ModuleInitializer::init);
}
@Override
public final void close() {
modules.forEach(ModuleInitializer::close);
}
@Override
public final void init(Config config, Context context) throws ApplicationBootInitializerException {
log.info(String.format("%s init application at %s (arguments: %s).", ApplicationBoot.BOOT_LOG_PREFIX, new Date(), Arrays.toString(getArgs())));
long t0 = System.nanoTime();
try { // 1 - init configuration
config.initConfig(new Properties()/*getResourceManager().getResource(CaliResourceManager.DefaultBootInitializerResources.application)*/, getArgs());
StringBuilder configBuilder = new StringBuilder(String.format("%s Configuration initialized with values:", ApplicationBoot.BOOT_LOG_PREFIX));
config.printConfigurationOptions(configBuilder);
log.info(configBuilder.toString());
} catch (Exception e) {
throw new ApplicationBootInitializerException("Can't load config application values", e);
}
registerResources(config);
try {// 2 - init user directories
initUserDirectories(config);
log.info(String.format("%s User directories (%s) initialized.", ApplicationBoot.BOOT_LOG_PREFIX, config.getDataDirectory()));
} catch (Exception e) {
throw new ApplicationBootInitializerException("Can't init user directories", e);
}
try {// 3 - init log
initLog(config);
log.info(String.format("%s Logger initialized (use configuration file: %s.", ApplicationBoot.BOOT_LOG_PREFIX, config.getLogConfigurationFile()));
} catch (Exception e) {
throw new ApplicationBootInitializerException("Can't init log", e);
}
try {// 4 - init i18n
initI18n(config);
log.info(String.format("%s I18n (locale %s) is initialized.", ApplicationBoot.BOOT_LOG_PREFIX, config.getApplicationLocale().getDisplayLanguage()));
} catch (Exception e) {
throw new ApplicationBootInitializerException("Can't init i18n", e);
}
try {// 5 - init ui configurations
initUIConfiguration(config);
} catch (Exception e) {
throw new ApplicationBootInitializerException("Can't init ui configuration", e);
}
try {// 6 - extra init
initExtra(config, context);
} catch (Exception e) {
throw new ApplicationBootInitializerException("Can't init extra", e);
}
try {// 7 - init components
initComponents(config, context);
} catch (Exception e) {
throw new ApplicationBootInitializerException("Can't init components", e);
}
String time = Strings.convertTime(t0, System.nanoTime());
log.info(String.format("%s Context was initialized in %s.", ApplicationBoot.BOOT_LOG_PREFIX, time));
}
protected void registerResources(Config config) {
resourceManager.registerResource(new ApplicationResourceManager.ClassPathResource(I18N_ARCHIVE));
resourceManager.registerResource(new ApplicationResourceManager.ClassPathResource(LOG_CONFIGURATION_FILE = config.get().replaceRecursiveOptions(LOG_CONFIGURATION_FILE)));
}
public void initExtra(Config config, Context context) {
}
protected final void initComponents(Config configuration, Context context) {
for (ApplicationContextComponent component : context.components()) {
component.set(context, configuration);
}
}
protected ApplicationResourceManager getResourceManager() {
return resourceManager;
}
protected void initI18n(Config config) {
I18n.close();
File i18nDirectory = config.getI18nDirectory();
I18nConfiguration i18nConfiguration = I18nConfiguration.createDefaultConfiguration();
UserI18nBootLoader i18nInitializer = new UserI18nBootLoader(i18nDirectory.toPath(), new DefaultI18nBootLoader(i18nConfiguration)) {
@Override
protected void createUserI18nLayout(Path directory, I18nLanguageProvider delegateLanguageProvider) throws Exception {
if (config.getI18nDefinitionFile().exists()) {
return;
}
super.createUserI18nLayout(directory,delegateLanguageProvider);
// add also a archive with all i18n stuff (says i18n bundle + templates)
URL resource = resourceManager.getResourceUrl(I18N_ARCHIVE);
File archive = new File(directory.getParent().toFile(), resourceManager.getResourceFilename(I18N_ARCHIVE));
try {
getResourceManager().copyResource(resource, archive, String.format("%s Copy i18n archive", ApplicationBoot.BOOT_LOG_PREFIX));
Zips.uncompressFiltred(archive, directory.toFile().getParentFile());
} finally {
if (Files.exists(archive.toPath())) {
try {
Files.delete(archive.toPath());
} catch (IOException e) {
log.error(String.format("Could not delete i18n archive %s", archive));
}
}
}
}
};
long t00 = System.nanoTime();
Locale locale = config.getApplicationLocale();
I18n.init(i18nInitializer, locale);
// TextTemplates.useDirectoryPath(new File(i18nDirectory, "ftl"));
log.debug("i18n language : " + locale);
log.debug("i18n loading time : " + Strings.convertTime(t00, System.nanoTime()));
}
protected void initLog(Config config) throws IOException {
File logFile = config.getLogConfigurationFile();
Preconditions.checkState(logFile.exists(), "Log config file %s does not exist.", logFile);
log.debug(String.format("%s Loading log configuration from %s", ApplicationBoot.BOOT_LOG_PREFIX, logFile));
List configLines = Files.readAllLines(logFile.toPath(), StandardCharsets.UTF_8);
List finalLogConfigurationProperties = ApplicationConfiguration.loadProperties(configLines, config.get());
StringBuilder finalConfiguration = new StringBuilder();
for (String finalLogConfigurationProperty : finalLogConfigurationProperties) {
finalConfiguration.append(finalLogConfigurationProperty).append("\n");
}
try (ByteArrayInputStream inputStream = new ByteArrayInputStream(finalConfiguration.toString().getBytes(StandardCharsets.UTF_8))) {
Configurator.initialize(null, new ConfigurationSource(inputStream));
}
log = LogManager.getLogger(getClass());
log.debug(String.format("%s Final log configuration done with file %s", ApplicationBoot.BOOT_LOG_PREFIX, logFile));
}
protected void initUserDirectories(Config config) throws IOException {
// 1 - user data directory
File dataDirectory = getResourceManager().createDirectory(config.getDataDirectory());
log.debug(String.format("user data directory : %s", dataDirectory));
// 2 - tmp directory
getResourceManager().createDirectory(config.getTmpDirectory());
FileUtils.cleanDirectory(config.getTmpDirectory());
// 3 - resources directory
File resourcesDirectory = config.getResourcesDirectory();
if (resourcesDirectory.exists() && !config.getApplicationBuildVersion().equals(config.getApplicationVersion())) {
// always clear resource directory
log.debug(String.format("clear user resource data directory: %s", resourcesDirectory));
if (config.getI18nDirectory().exists()) {
FileUtils.cleanDirectory(config.getI18nDirectory());
}
if (config.getLogConfigurationFile().exists()) {
FileUtils.deleteQuietly(config.getLogConfigurationFile());
}
}
getResourceManager().createDirectory(resourcesDirectory);
log.debug(String.format("user resource data directory: %s", resourcesDirectory));
// 4 - resources log configuration file
initLogFileDirectory(config);
}
protected void initLogFileDirectory(Config config) throws IOException {
File file = config.getLogConfigurationFile();
if (!file.exists()) {
String message = String.format("%s Copy default log configuration file: %s", ApplicationBoot.BOOT_LOG_PREFIX, file);
getResourceManager().copyResource(LOG_CONFIGURATION_FILE, file, message);
}
}
protected void initUIConfiguration(Config config) {
if (GraphicsEnvironment.isHeadless()) {
return;
}
// prepare ui look&feel and load ui properties
try {
SwingUtil.initNimbusLoookAndFeel();
} catch (Exception e) {
// could not find nimbus look-and-feel
log.warn("Could not use Look and Fell Nimbus, need at least version 1.6u10 of java.");
} catch (Throwable e) {
log.warn("No gui environment found");
}
UIResourcesProviders.load();
}
}