org.nuiton.jaxx.runtime.application.ApplicationResourceManager Maven / Gradle / Ivy
The newest version!
/*
* #%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%
*/
package org.nuiton.jaxx.runtime.application;
import io.ultreia.java4all.util.SortedProperties;
import io.ultreia.java4all.util.Zips;
import org.apache.commons.io.IOUtils;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import io.ultreia.java4all.config.spi.ConfigOptionDef;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.TreeMap;
/**
* La classe responsable du chargement de toutes les resources qui viennent de
* l'application et qui seont ensuite redispatchés dans le répertoire de
* resource de l'utilisateur.
*
* @author Tony Chemit - [email protected]
* @since 1.4
*/
public class ApplicationResourceManager {
private static final Logger log = LogManager.getLogger(ApplicationResourceManager.class);
private final Map resourceDefinitions;
private Map resources;
public ApplicationResourceManager() {
resourceDefinitions = new TreeMap<>();
}
public static URL getResource(String location) {
URL resource = ApplicationResourceManager.class.getResource(location);
try {
// test que la resource existe bien dans le class-path
try (InputStream in = openInternalStream(resource)) {
log.debug("opening: " + in);
}
return resource;
} catch (Exception e) {
throw new IllegalStateException("Could not treat internal resource " + location);
}
}
protected static InputStream openInternalStream(URL resource) {
try {
InputStream in = resource.openStream();
Objects.requireNonNull(in, "Could not find internal resource " + resource);
return in;
} catch (Exception e) {
throw new IllegalStateException("Could not treat internal resource " + resource);
}
}
public void registerResource(Resource resource) {
resourceDefinitions.put(resource.getLocation(), resource);
}
protected Map getResources() {
if (resources == null) {
resources = new TreeMap<>();
}
return resources;
}
public Properties getResourceProperties(String resource) throws IOException {
URL url = getRegistredResource(resource).getUrl();
return getResource(url);
}
private Properties getResource(URL url) throws IOException {
String path = url.toString();
Properties result = getResources().get(path);
if (result == null) {
result = load(url);
log.debug("Store configuration [" + path + "]");
getResources().put(path, result);
}
// toujours faire une copie pour eviter toute altération des
// configuration par défaut.
SortedProperties tmp = new SortedProperties();
tmp.putAll(result);
return tmp;
}
public Properties load(URL url) throws IOException {
Properties result;// chargement une unique fois de la resource
try (InputStream in = openInternalStream(url)) {
result = new Properties();
result.load(in);
}
return result;
}
public void copyResource(String resource, File file, String message) throws IOException {
try (FileOutputStream out = new FileOutputStream(file)) {
// on fait une copie brute en ne passant pas par un Properties
// qui perd le formatage et les commentaires
// chargement des ressources
// sauvegarde dans le fichier cible
try (InputStreamReader in = new InputStreamReader(new BufferedInputStream(openInternalStream(getRegistredResource(resource).getUrl())), StandardCharsets.UTF_8)) {
IOUtils.copy(in, out, StandardCharsets.UTF_8);
}
log.debug(message);
}
}
private Resource getRegistredResource(String resource) {
return Objects.requireNonNull(resourceDefinitions.get(resource));
}
public void copyResource(URL resource, File file, String message) throws IOException {
try (FileOutputStream out = new FileOutputStream(file)) {
try (InputStream in = openInternalStream(resource)) {
// sauvegarde dans le fichier cible
IOUtils.copy(in, out);
}
log.debug(message);
}
}
/**
* Créer le répertoire si nécessaire à partir le l'option donnée.
*
* @param config la configuration utilisée
* @param option l'option qui représentent le répertoire.
* @return le fichier
* @throws IOException pour tout problème de création de répertoire
*/
public File createDirectory(ApplicationConfiguration config, ConfigOptionDef option) throws IOException {
File dir = config.get().getOptionAsFile(option.getKey());
createDirectory(dir);
return dir;
}
/**
* Créer tous les répertoires parents nécessaires à partir des options sur
* répertoire ou fichier.
*
* @param config la configuration utilisée
* @param options les options qui représentent des répertoires ou fichiers.
* @throws IOException pour tout problème de création de répertoire
*/
public void createParentDirectory(ApplicationConfiguration config, ConfigOptionDef... options) throws IOException {
for (ConfigOptionDef option : options) {
File dir = config.get().getOptionAsFile(option.getKey()).getParentFile();
createDirectory(dir);
}
}
/**
* Créer un répertoire s'il n'existe pas.
*
* @param dir le répertoire à créer
* @return le fichier
* @throws IOException pour tout problème de création de répertoire
*/
protected File createDirectory(File dir) throws IOException {
if (!dir.exists()) {
log.debug(String.format("Create directory %s", dir));
log.debug(String.format("Directory %s exists.", dir));
boolean b = dir.mkdirs();
if (!b) {
throw new IOException(String.format("Can not create directory: %s", dir));
}
}
return dir;
}
public void unzipToDirectory(String resourceName, ApplicationConfiguration config, ConfigOptionDef option) throws IOException {
File dir = config.get().getOptionAsFile(option.getKey());
createDirectory(dir);
URL resourceUrl = getResourceUrl(resourceName);
try (InputStream inputStream = openInternalStream(resourceUrl)) {
Zips.uncompress(inputStream, dir);
}
}
public URL getResourceUrl(String resource) {
return getRegistredResource(resource).getUrl();
}
public String getResourceFilename(String resource) {
return getRegistredResource(resource).getFilename();
}
public interface Resource {
URL getUrl();
boolean exists(File directory);
File getFile(File directory);
String getFilename();
String getLocation();
}
public static class ClassPathResource implements Resource {
private final String location;
private URL url;
public ClassPathResource(String location) {
this.location = location;
}
@Override
public String getLocation() {
return location;
}
@Override
public URL getUrl() {
if (url == null) {
url = ApplicationResourceManager.getResource(location);
}
return url;
}
@Override
public boolean exists(File directory) {
File file = getFile(directory);
return file.exists();
}
@Override
public File getFile(File directory) {
return new File(directory, getFilename());
}
@Override
public String getFilename() {
return location.substring(1);
}
}
}