mirror of https://github.com/halo-dev/halo
Complete copy folder from jar file
parent
52c3081577
commit
1b249de99e
|
@ -1,6 +1,5 @@
|
||||||
package run.halo.app.listener;
|
package run.halo.app.listener;
|
||||||
|
|
||||||
import cn.hutool.core.io.FileUtil;
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import freemarker.template.TemplateModelException;
|
import freemarker.template.TemplateModelException;
|
||||||
|
@ -20,10 +19,12 @@ import run.halo.app.model.support.HaloConst;
|
||||||
import run.halo.app.service.OptionService;
|
import run.halo.app.service.OptionService;
|
||||||
import run.halo.app.service.ThemeService;
|
import run.halo.app.service.ThemeService;
|
||||||
import run.halo.app.service.UserService;
|
import run.halo.app.service.UserService;
|
||||||
|
import run.halo.app.utils.FileUtils;
|
||||||
import run.halo.app.utils.HaloUtils;
|
import run.halo.app.utils.HaloUtils;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.nio.file.*;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -158,21 +159,40 @@ public class StartedListener implements ApplicationListener<ApplicationStartedEv
|
||||||
private void initThemes() {
|
private void initThemes() {
|
||||||
// Whether the blog has initialized
|
// Whether the blog has initialized
|
||||||
Boolean isInstalled = optionService.getByPropertyOrDefault(PrimaryProperties.IS_INSTALLED, Boolean.class, false);
|
Boolean isInstalled = optionService.getByPropertyOrDefault(PrimaryProperties.IS_INSTALLED, Boolean.class, false);
|
||||||
|
|
||||||
|
if (isInstalled) {
|
||||||
|
// Skip
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (isInstalled) {
|
String themeClassPath = ResourceUtils.CLASSPATH_URL_PREFIX + ThemeService.THEME_FOLDER;
|
||||||
// Skip
|
|
||||||
return;
|
URI themeUri = ResourceUtils.getURL(themeClassPath).toURI();
|
||||||
|
|
||||||
|
Path source;
|
||||||
|
|
||||||
|
if (themeUri.getScheme().equalsIgnoreCase("jar")) {
|
||||||
|
// Create new file system for jar
|
||||||
|
FileSystem fileSystem = FileSystems.newFileSystem(themeUri, Collections.emptyMap());
|
||||||
|
source = fileSystem.getPath("/BOOT-INF/classes/" + ThemeService.THEME_FOLDER);
|
||||||
|
} else {
|
||||||
|
source = Paths.get(themeUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
File internalThemePath = new File(ResourceUtils.getURL(ResourceUtils.CLASSPATH_URL_PREFIX).getPath(), "templates/themes");
|
// Create theme folder
|
||||||
File[] internalThemes = internalThemePath.listFiles();
|
Path themePath = themeService.getBasePath();
|
||||||
if (null != internalThemes) {
|
|
||||||
for (File theme : internalThemes) {
|
if (Files.notExists(themePath)) {
|
||||||
FileUtil.copy(theme, themeService.getThemeBasePath(), true);
|
log.info("Copying theme folder from [{}] to [{}]", source, themePath);
|
||||||
}
|
|
||||||
|
FileUtils.copyFolder(source, themePath);
|
||||||
|
} else {
|
||||||
|
log.info("Skip copying theme folder due to existence of theme folder");
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException("Init internal theme to user path error", e);
|
throw new RuntimeException("Init internal theme to user path error", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,43 @@ import java.util.Optional;
|
||||||
*/
|
*/
|
||||||
public interface ThemeService {
|
public interface ThemeService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Theme property file name.
|
||||||
|
*/
|
||||||
|
String THEME_PROPERTY_FILE_NAME = "theme.properties";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration file name.
|
||||||
|
*/
|
||||||
|
String[] OPTIONS_NAMES = {"options.yaml", "options.yml"};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of file that can be modified.
|
||||||
|
*/
|
||||||
|
String[] CAN_EDIT_SUFFIX = {"ftl", "css", "js"};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These file names cannot be displayed.
|
||||||
|
*/
|
||||||
|
String[] FILTER_FILES = {".git", ".DS_Store", THEME_PROPERTY_FILE_NAME, "options.yaml", "option.yml"};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Theme folder location.
|
||||||
|
*/
|
||||||
|
String THEME_FOLDER = "templates/themes";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render template.
|
||||||
|
*/
|
||||||
|
String RENDER_TEMPLATE = "themes/%s/%s";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Theme cache key.
|
||||||
|
*/
|
||||||
|
String THEMES_CACHE_KEY = "themes";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get theme property by theme id.
|
* Get theme property by theme id.
|
||||||
*
|
*
|
||||||
|
|
|
@ -47,43 +47,6 @@ import static run.halo.app.model.support.HaloConst.DEFAULT_THEME_NAME;
|
||||||
@Service
|
@Service
|
||||||
public class ThemeServiceImpl implements ThemeService {
|
public class ThemeServiceImpl implements ThemeService {
|
||||||
|
|
||||||
/**
|
|
||||||
* Theme property file name.
|
|
||||||
*/
|
|
||||||
private final static String THEME_PROPERTY_FILE_NAME = "theme.properties";
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configuration file name.
|
|
||||||
*/
|
|
||||||
private final static String[] OPTIONS_NAMES = {"options.yaml", "options.yml"};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The type of file that can be modified.
|
|
||||||
*/
|
|
||||||
private static String[] CAN_EDIT_SUFFIX = {"ftl", "css", "js"};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* These file names cannot be displayed.
|
|
||||||
*/
|
|
||||||
private static String[] FILTER_FILES = {".git", ".DS_Store", THEME_PROPERTY_FILE_NAME, "options.yaml", "option.yml"};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Theme folder location.
|
|
||||||
*/
|
|
||||||
private final static String THEME_FOLDER = "templates/themes";
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render template.
|
|
||||||
*/
|
|
||||||
private final static String RENDER_TEMPLATE = "themes/%s/%s";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Theme cache key.
|
|
||||||
*/
|
|
||||||
private final static String THEMES_CACHE_KEY = "themes";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Theme work directory.
|
* Theme work directory.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
package run.halo.app.utils;
|
||||||
|
|
||||||
|
import org.springframework.lang.NonNull;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.*;
|
||||||
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* File utilities.
|
||||||
|
*
|
||||||
|
* @author johnniang
|
||||||
|
* @date 4/9/19
|
||||||
|
*/
|
||||||
|
public class FileUtils {
|
||||||
|
|
||||||
|
private FileUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies folder.
|
||||||
|
*
|
||||||
|
* @param source source path must not be null
|
||||||
|
* @param target target path must not be null
|
||||||
|
*/
|
||||||
|
public static void copyFolder(@NonNull Path source, @NonNull Path target) throws IOException {
|
||||||
|
Assert.notNull(source, "Source path must not be null");
|
||||||
|
Assert.notNull(target, "Target path must not be null");
|
||||||
|
|
||||||
|
Files.walkFileTree(source, new SimpleFileVisitor<Path>() {
|
||||||
|
|
||||||
|
private Path current;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
|
||||||
|
current = target.resolve(source.relativize(dir).toString());
|
||||||
|
Files.createDirectories(current);
|
||||||
|
return FileVisitResult.CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||||
|
Files.copy(file, target.resolve(source.relativize(file).toString()), StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
return FileVisitResult.CONTINUE;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue