fix #2217 add theme
This commit is contained in:
parent
88339b8001
commit
c36d96bb4f
7 changed files with 234 additions and 26 deletions
|
@ -25,7 +25,6 @@ import java.util.stream.Collectors;
|
|||
import org.codelibs.fess.app.web.base.FessAdminAction;
|
||||
import org.codelibs.fess.helper.PluginHelper;
|
||||
import org.codelibs.fess.helper.PluginHelper.Artifact;
|
||||
import org.codelibs.fess.helper.PluginHelper.ArtifactType;
|
||||
import org.codelibs.fess.util.ComponentUtil;
|
||||
import org.codelibs.fess.util.RenderDataUtil;
|
||||
import org.lastaflute.web.Execute;
|
||||
|
@ -108,7 +107,7 @@ public class AdminPluginAction extends FessAdminAction {
|
|||
|
||||
public static Map<String, String> beanToMap(final Artifact artifact) {
|
||||
final Map<String, String> item = new HashMap<>();
|
||||
item.put("type", ArtifactType.getType(artifact.getName()).getId());
|
||||
item.put("type", artifact.getType().getId());
|
||||
item.put("id", artifact.getName() + ":" + artifact.getVersion());
|
||||
item.put("name", artifact.getName());
|
||||
item.put("version", artifact.getVersion());
|
||||
|
@ -124,7 +123,7 @@ public class AdminPluginAction extends FessAdminAction {
|
|||
public static void installArtifact(final Artifact artifact) {
|
||||
new Thread(() -> {
|
||||
final PluginHelper pluginHelper = ComponentUtil.getPluginHelper();
|
||||
final Artifact[] artifacts = pluginHelper.getInstalledArtifacts(ArtifactType.getType(artifact.getName()));
|
||||
final Artifact[] artifacts = pluginHelper.getInstalledArtifacts(artifact.getType());
|
||||
try {
|
||||
pluginHelper.installArtifact(artifact);
|
||||
} catch (final Exception e) {
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright 2012-2019 CodeLibs Project and the Others.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific language
|
||||
* governing permissions and limitations under the License.
|
||||
*/
|
||||
package org.codelibs.fess.exception;
|
||||
|
||||
public class ThemeException extends FessSystemException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ThemeException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public ThemeException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
|
@ -30,7 +30,6 @@ import java.util.concurrent.TimeUnit;
|
|||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.xml.XMLConstants;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
|
@ -193,14 +192,35 @@ public class PluginHelper {
|
|||
} catch (final Exception e) {
|
||||
throw new PluginException("Failed to install the artifact " + artifact.getName(), e);
|
||||
}
|
||||
|
||||
switch (artifact.getType()) {
|
||||
case DATA_STORE:
|
||||
break;
|
||||
case THEME:
|
||||
ComponentUtil.getThemeHelper().install(artifact);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteInstalledArtifact(final Artifact artifact) {
|
||||
final String fileName = artifact.getFileName();
|
||||
final Path jarPath = Paths.get(getPluginPath().toString(), fileName);
|
||||
final Path jarPath = Paths.get(ResourceUtil.getPluginPath().toString(), fileName);
|
||||
if (!Files.exists(jarPath)) {
|
||||
throw new PluginException(fileName + " does not exist.");
|
||||
}
|
||||
|
||||
switch (artifact.getType()) {
|
||||
case DATA_STORE:
|
||||
break;
|
||||
case THEME:
|
||||
ComponentUtil.getThemeHelper().uninstall(artifact);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
Files.delete(jarPath);
|
||||
} catch (final IOException e) {
|
||||
|
@ -220,10 +240,6 @@ public class PluginHelper {
|
|||
return null;
|
||||
}
|
||||
|
||||
protected Path getPluginPath() {
|
||||
return Paths.get(ComponentUtil.getComponent(ServletContext.class).getRealPath("/WEB-INF/plugin"));
|
||||
}
|
||||
|
||||
public static class Artifact {
|
||||
protected final String name;
|
||||
protected final String version;
|
||||
|
@ -255,14 +271,18 @@ public class PluginHelper {
|
|||
return url;
|
||||
}
|
||||
|
||||
public ArtifactType getType() {
|
||||
return ArtifactType.getType(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Artifact [name=" + name + ", version=" + version + "]";
|
||||
return name + ":" + version;
|
||||
}
|
||||
}
|
||||
|
||||
public enum ArtifactType {
|
||||
DATA_STORE("fess-ds"), UNKNOWN("unknown");
|
||||
DATA_STORE("fess-ds"), THEME("fess-theme"), UNKNOWN("unknown");
|
||||
|
||||
private final String id;
|
||||
|
||||
|
@ -277,6 +297,8 @@ public class PluginHelper {
|
|||
public static ArtifactType getType(final String name) {
|
||||
if (name.startsWith(DATA_STORE.getId())) {
|
||||
return DATA_STORE;
|
||||
} else if (name.startsWith(THEME.getId())) {
|
||||
return THEME;
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
|
130
src/main/java/org/codelibs/fess/helper/ThemeHelper.java
Normal file
130
src/main/java/org/codelibs/fess/helper/ThemeHelper.java
Normal file
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Copyright 2012-2019 CodeLibs Project and the Others.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific language
|
||||
* governing permissions and limitations under the License.
|
||||
*/
|
||||
package org.codelibs.fess.helper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileVisitOption;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Comparator;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import org.codelibs.core.lang.StringUtil;
|
||||
import org.codelibs.fess.exception.ThemeException;
|
||||
import org.codelibs.fess.helper.PluginHelper.Artifact;
|
||||
import org.codelibs.fess.helper.PluginHelper.ArtifactType;
|
||||
import org.codelibs.fess.util.ResourceUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ThemeHelper {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ThemeHelper.class);
|
||||
|
||||
public void install(Artifact artifact) {
|
||||
Path jarPath = getJarFile(artifact);
|
||||
String themeName = getThemeName(artifact);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Theme: " + themeName);
|
||||
}
|
||||
try (ZipInputStream zis = new ZipInputStream(Files.newInputStream(jarPath))) {
|
||||
ZipEntry entry;
|
||||
while ((entry = zis.getNextEntry()) != null) {
|
||||
if (!entry.isDirectory()) {
|
||||
String[] names = entry.getName().split("/");
|
||||
if (names.length < 2) {
|
||||
continue;
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Loading " + entry.getName());
|
||||
}
|
||||
if ("view".equals(names[0])) {
|
||||
names[0] = themeName;
|
||||
Path path = ResourceUtil.getViewTemplatePath(names);
|
||||
Files.createDirectories(path.getParent());
|
||||
Files.copy(zis, path);
|
||||
} else if ("css".equals(names[0])) {
|
||||
names[0] = themeName;
|
||||
Path path = ResourceUtil.getCssPath(names);
|
||||
Files.createDirectories(path.getParent());
|
||||
Files.copy(zis, path);
|
||||
} else if ("js".equals(names[0])) {
|
||||
names[0] = themeName;
|
||||
Path path = ResourceUtil.getJavaScriptPath(names);
|
||||
Files.createDirectories(path.getParent());
|
||||
Files.copy(zis, path);
|
||||
} else if ("images".equals(names[0])) {
|
||||
names[0] = themeName;
|
||||
Path path = ResourceUtil.getImagePath(names);
|
||||
Files.createDirectories(path.getParent());
|
||||
Files.copy(zis, path);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new ThemeException("Failed to install " + artifact);
|
||||
}
|
||||
}
|
||||
|
||||
public void uninstall(Artifact artifact) {
|
||||
String themeName = getThemeName(artifact);
|
||||
|
||||
Path viewPath = ResourceUtil.getViewTemplatePath(themeName);
|
||||
closeQuietly(viewPath);
|
||||
Path imagePath = ResourceUtil.getImagePath(themeName);
|
||||
closeQuietly(imagePath);
|
||||
Path cssPath = ResourceUtil.getCssPath(themeName);
|
||||
closeQuietly(cssPath);
|
||||
Path jsPath = ResourceUtil.getJavaScriptPath(themeName);
|
||||
closeQuietly(jsPath);
|
||||
}
|
||||
|
||||
protected String getThemeName(Artifact artifact) {
|
||||
String themeName = artifact.getName().substring(ArtifactType.THEME.getId().length() + 1);
|
||||
if (StringUtil.isBlank(themeName)) {
|
||||
throw new ThemeException("Theme name is empty: " + artifact);
|
||||
}
|
||||
return themeName;
|
||||
}
|
||||
|
||||
protected void closeQuietly(Path dir) {
|
||||
try (Stream<Path> walk = Files.walk(dir, FileVisitOption.FOLLOW_LINKS)) {
|
||||
walk.sorted(Comparator.reverseOrder()).forEach(f -> {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Deleting " + f);
|
||||
}
|
||||
try {
|
||||
Files.delete(f);
|
||||
} catch (IOException e) {
|
||||
logger.warn("Failed to delete " + f, e);
|
||||
}
|
||||
});
|
||||
Files.deleteIfExists(dir);
|
||||
} catch (IOException e) {
|
||||
logger.warn("Failed to delete " + dir, e);
|
||||
}
|
||||
}
|
||||
|
||||
protected Path getJarFile(Artifact artifact) {
|
||||
Path jarPath = ResourceUtil.getPluginPath(artifact.getFileName());
|
||||
if (!Files.exists(jarPath)) {
|
||||
throw new ThemeException(artifact.getFileName() + " does not exist.");
|
||||
}
|
||||
return jarPath;
|
||||
}
|
||||
|
||||
}
|
|
@ -61,6 +61,7 @@ import org.codelibs.fess.helper.SambaHelper;
|
|||
import org.codelibs.fess.helper.SearchLogHelper;
|
||||
import org.codelibs.fess.helper.SuggestHelper;
|
||||
import org.codelibs.fess.helper.SystemHelper;
|
||||
import org.codelibs.fess.helper.ThemeHelper;
|
||||
import org.codelibs.fess.helper.UserAgentHelper;
|
||||
import org.codelibs.fess.helper.UserInfoHelper;
|
||||
import org.codelibs.fess.helper.ViewHelper;
|
||||
|
@ -90,6 +91,8 @@ public final class ComponentUtil {
|
|||
|
||||
private static Map<String, Object> componentMap = new HashMap<>();
|
||||
|
||||
private static final String THEME_HELPER = "themeHelper";
|
||||
|
||||
private static final String PLUGIN_HELPER = "pluginHelper";
|
||||
|
||||
private static final String LANGUAGE_HELPER = "languageHelper";
|
||||
|
@ -448,6 +451,10 @@ public final class ComponentUtil {
|
|||
return getComponent(PLUGIN_HELPER);
|
||||
}
|
||||
|
||||
public static ThemeHelper getThemeHelper() {
|
||||
return getComponent(THEME_HELPER);
|
||||
}
|
||||
|
||||
public static <T> T getComponent(final Class<T> clazz) {
|
||||
try {
|
||||
return SingletonLaContainer.getComponent(clazz);
|
||||
|
|
|
@ -80,50 +80,62 @@ public class ResourceUtil {
|
|||
if (StringUtil.isNotBlank(confPath)) {
|
||||
return Paths.get(confPath, names);
|
||||
}
|
||||
return getPath("conf", names);
|
||||
return getPath("WEB-INF/", "conf", names);
|
||||
}
|
||||
|
||||
public static Path getClassesPath(final String... names) {
|
||||
return getPath("classes", names);
|
||||
return getPath("WEB-INF/", "classes", names);
|
||||
}
|
||||
|
||||
public static Path getOrigPath(final String... names) {
|
||||
return getPath("orig", names);
|
||||
return getPath("WEB-INF/", "orig", names);
|
||||
}
|
||||
|
||||
public static Path getMailTemplatePath(final String... names) {
|
||||
return getPath("mail", names);
|
||||
return getPath("WEB-INF/", "mail", names);
|
||||
}
|
||||
|
||||
public static Path getViewTemplatePath(final String... names) {
|
||||
return getPath("view", names);
|
||||
return getPath("WEB-INF/", "view", names);
|
||||
}
|
||||
|
||||
public static Path getDictionaryPath(final String... names) {
|
||||
return getPath("dict", names);
|
||||
return getPath("WEB-INF/", "dict", names);
|
||||
}
|
||||
|
||||
public static Path getThumbnailPath(final String... names) {
|
||||
return getPath("thumbnails", names);
|
||||
return getPath("WEB-INF/", "thumbnails", names);
|
||||
}
|
||||
|
||||
public static Path getSitePath(final String... names) {
|
||||
return getPath("site", names);
|
||||
return getPath("WEB-INF/", "site", names);
|
||||
}
|
||||
|
||||
public static Path getPluginPath(final String... names) {
|
||||
return getPath("plugin", names);
|
||||
return getPath("WEB-INF/", "plugin", names);
|
||||
}
|
||||
|
||||
public static Path getProjectPropertiesFile() {
|
||||
return getPath("", "project.properties");
|
||||
return getPath("WEB-INF/", StringUtil.EMPTY, "project.properties");
|
||||
}
|
||||
|
||||
protected static Path getPath(final String base, final String... names) {
|
||||
public static Path getImagePath(final String... names) {
|
||||
return getPath(StringUtil.EMPTY, "images", names);
|
||||
}
|
||||
|
||||
public static Path getCssPath(final String... names) {
|
||||
return getPath(StringUtil.EMPTY, "css", names);
|
||||
}
|
||||
|
||||
public static Path getJavaScriptPath(final String... names) {
|
||||
return getPath(StringUtil.EMPTY, "js", names);
|
||||
}
|
||||
|
||||
protected static Path getPath(final String root, final String base, final String... names) {
|
||||
|
||||
try {
|
||||
final ServletContext servletContext = ComponentUtil.getComponent(ServletContext.class);
|
||||
final String webinfPath = servletContext.getRealPath("/WEB-INF/" + base);
|
||||
final String webinfPath = servletContext.getRealPath("/" + root + base);
|
||||
if (webinfPath != null) {
|
||||
if (Files.exists(Paths.get(webinfPath))) {
|
||||
return Paths.get(webinfPath, names);
|
||||
|
@ -132,15 +144,15 @@ public class ResourceUtil {
|
|||
} catch (final Throwable e) {
|
||||
// ignore
|
||||
}
|
||||
final String webinfBase = "WEB-INF/" + base;
|
||||
final String webinfBase = root + base;
|
||||
if (Files.exists(Paths.get(webinfBase))) {
|
||||
return Paths.get(webinfBase, names);
|
||||
}
|
||||
final String srcWebInfBase = "src/main/webapps/WEB-INF/" + base;
|
||||
final String srcWebInfBase = "src/main/webapps" + root + base;
|
||||
if (Files.exists(Paths.get(srcWebInfBase))) {
|
||||
return Paths.get(srcWebInfBase, names);
|
||||
}
|
||||
final String targetWebInfBase = "target/fess/WEB-INF/" + base;
|
||||
final String targetWebInfBase = "target/fess/" + root + base;
|
||||
if (Files.exists(Paths.get(targetWebInfBase))) {
|
||||
return Paths.get(targetWebInfBase, names);
|
||||
}
|
||||
|
@ -157,6 +169,9 @@ public class ResourceUtil {
|
|||
return new File[0];
|
||||
}
|
||||
final File libDir = new File(libPath);
|
||||
if (!libDir.exists()) {
|
||||
return new File[0];
|
||||
}
|
||||
return libDir.listFiles((FilenameFilter) (file, name) -> name.startsWith(namePrefix));
|
||||
}
|
||||
|
||||
|
@ -170,6 +185,9 @@ public class ResourceUtil {
|
|||
return new File[0];
|
||||
}
|
||||
final File libDir = new File(libPath);
|
||||
if (!libDir.exists()) {
|
||||
return new File[0];
|
||||
}
|
||||
return libDir.listFiles((FilenameFilter) (file, name) -> name.startsWith(namePrefix));
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
</component>
|
||||
<component name="pluginHelper" class="org.codelibs.fess.helper.PluginHelper">
|
||||
</component>
|
||||
<component name="themeHelper" class="org.codelibs.fess.helper.ThemeHelper">
|
||||
</component>
|
||||
<component name="queryStringBuilder" class="org.codelibs.fess.util.QueryStringBuilder" instance="prototype">
|
||||
</component>
|
||||
<component name="queryParser" class="org.apache.lucene.queryparser.ext.ExtendableQueryParser" instance="prototype">
|
||||
|
|
Loading…
Add table
Reference in a new issue