org.nuiton.i18n.init.UserI18nInitializer Maven / Gradle / Ivy
/*
* #%L
* I18n :: Api
* %%
* Copyright (C) 2004 - 2017 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.i18n.init;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.Properties;
import org.apache.commons.io.IOUtils;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.nuiton.i18n.bundle.I18nBundle;
import org.nuiton.i18n.bundle.I18nBundleEntry;
import org.nuiton.i18n.bundle.I18nBundleUtil;
import org.nuiton.i18n.format.I18nMessageFormatter;
/**
* Initializer which expose i18n resources in the {@link #userDirectory}, then
* use resources from this user directories.
*
* @author Tony Chemit - [email protected]
* @since 1.1
*/
public class UserI18nInitializer extends DefaultI18nInitializer {
/** Logger. */
private static final Logger log = LogManager.getLogger(UserI18nInitializer.class);
/** the user directory where to store the i18n resources. */
protected final File userDirectory;
/**
* the delegate initializer to obtain default i18n resources to put in user
* directory.
*/
protected final DefaultI18nInitializer delegate;
public UserI18nInitializer(File userDirectory,
DefaultI18nInitializer delegate)
throws NullPointerException {
this(null, userDirectory, delegate);
}
public UserI18nInitializer(String i18nPath,
File userDirectory,
DefaultI18nInitializer delegate)
throws NullPointerException {
super(delegate == null ? null : delegate.getBundleName(),
null,
i18nPath == null ? "" : i18nPath
);
if (userDirectory == null) {
throw new NullPointerException(
"parameter 'userDirectory' can not be null");
}
if (delegate == null) {
throw new NullPointerException(
"parameter 'delegate' can not be null");
}
this.userDirectory = userDirectory;
this.delegate = delegate;
}
public File getUserDirectory() {
return userDirectory;
}
public DefaultI18nInitializer getDelegate() {
return delegate;
}
@Override
public Charset getEncoding() {
return getDelegate().getEncoding();
}
@Override
public void setEncoding(Charset encoding) {
getDelegate().setEncoding(encoding);
}
@Override
public I18nMessageFormatter getMessageFormatter() {
return getDelegate().getMessageFormatter();
}
@Override
public void setMessageFormatter(I18nMessageFormatter messageFormatter) {
getDelegate().setMessageFormatter(messageFormatter);
}
@Override
public I18nBundle[] resolvBundles() throws Exception {
File directory = getUserDirectory();
boolean isNew = !directory.exists();
// creates the user directory and fill it with i18n resources
// coming from default initializer
createUserI18nLayout(directory);
// use a new classloader directly on the directory
setLoader(new URLClassLoader(new URL[]{directory.toURI().toURL()}));
// now can grab bundles from the user external directory
I18nBundle[] bundles = super.resolvBundles();
if (!isNew) {
// will update directory if required
updateUserI18nLayout(directory, bundles);
}
return bundles;
}
/**
* Creates the user i18n structure or fill it if required.
*
* will use the default initializer to obtain i18n resources from default
* system, then copy them to the user directory.
*
* @param directory the directory where to export i18n resources
* @throws Exception if any pb
*/
protected void createUserI18nLayout(File directory) throws Exception {
// if user i18n directory does not exists create it
// Then fill it (if files not exists)
boolean b = directory.exists() || directory.mkdirs();
if (!b) {
throw new IOException(String.format("could not create directory %s", directory));
}
Properties definition = new Properties();
String prefixURL = getDelegate().resolvDefinition(definition);
String filename = String.format(UNIQUE_BUNDLE_DEF, getBundleName());
File f = new File(directory, filename);
if (!f.exists()) {
try (BufferedWriter outStream = Files.newBufferedWriter(f.toPath(), encoding)) {
definition.store(outStream, String.format("Generated by %s", getClass().getName()));
}
}
// detect bundles urls
URL[] urls = resolvURLs(prefixURL, definition);
// detect bundles
I18nBundle[] bundles = resolvBundles(urls);
// detect bundles entries
I18nBundleEntry[] entries = I18nBundleUtil.getBundleEntries(bundles);
// copy all bundle entries resource
for (I18nBundleEntry e : entries) {
URL url = e.getPath();
if (log.isInfoEnabled()) {
log.info("I18n file to load : " + url);
}
String path = url.getPath();
String name = path.substring(path.lastIndexOf("/"));
File dst = new File(directory, name);
if (dst.exists()) {
if (log.isDebugEnabled()) {
log.debug("Keep user file " + dst);
}
continue;
}
if (log.isInfoEnabled()) {
log.info("Create user file to create : " + dst);
}
// copy file
try (BufferedWriter outStream = Files.newBufferedWriter(dst.toPath(), encoding)) {
try {
IOUtils.copy(url.openStream(), outStream, encoding);
} finally {
outStream.close();
}
}
}
}
/**
* Hook to update the user i18n structure.
*
* If you wants to do something specific, overriddes this method.
*
* @param directory the user directory where are i18n resources
* @param bundles the user i18n bundles
*/
public void updateUserI18nLayout(File directory, I18nBundle[] bundles) {
// by default nothing to do, change this if you wants something
}
}