fix #2217 add theme

This commit is contained in:
Shinsuke Sugaya 2019-08-23 22:48:18 +09:00
parent 88339b8001
commit c36d96bb4f
7 changed files with 234 additions and 26 deletions

View file

@ -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) {

View file

@ -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);
}
}

View file

@ -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;
}

View 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;
}
}

View file

@ -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);

View file

@ -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));
}

View file

@ -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">