View Javadoc
1   /*
2    * Copyright 2012-2021 CodeLibs Project and the Others.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
15   */
16  package org.codelibs.fess.helper;
17  
18  import java.io.IOException;
19  import java.nio.file.FileVisitOption;
20  import java.nio.file.Files;
21  import java.nio.file.Path;
22  import java.nio.file.StandardCopyOption;
23  import java.util.Comparator;
24  import java.util.stream.Stream;
25  import java.util.zip.ZipEntry;
26  import java.util.zip.ZipInputStream;
27  
28  import org.apache.logging.log4j.LogManager;
29  import org.apache.logging.log4j.Logger;
30  import org.codelibs.core.lang.StringUtil;
31  import org.codelibs.core.stream.StreamUtil;
32  import org.codelibs.fess.exception.ThemeException;
33  import org.codelibs.fess.helper.PluginHelper.Artifact;
34  import org.codelibs.fess.helper.PluginHelper.ArtifactType;
35  import org.codelibs.fess.util.ResourceUtil;
36  
37  public class ThemeHelper {
38      private static final Logger logger = LogManager.getLogger(ThemeHelper.class);
39  
40      public void install(final Artifact artifact) {
41          final Path jarPath = getJarFile(artifact);
42          final String themeName = getThemeName(artifact);
43          if (logger.isDebugEnabled()) {
44              logger.debug("Theme: {}", themeName);
45          }
46          try (ZipInputStream zis = new ZipInputStream(Files.newInputStream(jarPath))) {
47              ZipEntry entry;
48              while ((entry = zis.getNextEntry()) != null) {
49                  if (!entry.isDirectory()) {
50                      final String[] names = StreamUtil.split(entry.getName(), "/")
51                              .get(stream -> stream.filter(s -> !"..".equals(s)).toArray(n -> new String[n]));
52                      if (names.length < 2) {
53                          continue;
54                      }
55                      if (logger.isDebugEnabled()) {
56                          logger.debug("Loading {}", entry.getName());
57                      }
58                      if ("view".equals(names[0])) {
59                          names[0] = themeName;
60                          final Path path = ResourceUtil.getViewTemplatePath(names);
61                          Files.createDirectories(path.getParent());
62                          Files.copy(zis, path, StandardCopyOption.REPLACE_EXISTING);
63                      } else if ("css".equals(names[0])) {
64                          names[0] = themeName;
65                          final Path path = ResourceUtil.getCssPath(names);
66                          Files.createDirectories(path.getParent());
67                          Files.copy(zis, path, StandardCopyOption.REPLACE_EXISTING);
68                      } else if ("js".equals(names[0])) {
69                          names[0] = themeName;
70                          final Path path = ResourceUtil.getJavaScriptPath(names);
71                          Files.createDirectories(path.getParent());
72                          Files.copy(zis, path, StandardCopyOption.REPLACE_EXISTING);
73                      } else if ("images".equals(names[0])) {
74                          names[0] = themeName;
75                          final Path path = ResourceUtil.getImagePath(names);
76                          Files.createDirectories(path.getParent());
77                          Files.copy(zis, path, StandardCopyOption.REPLACE_EXISTING);
78                      }
79                  }
80              }
81          } catch (final IOException e) {
82              throw new ThemeException("Failed to install " + artifact, e);
83          }
84      }
85  
86      public void uninstall(final Artifact artifact) {
87          final String themeName = getThemeName(artifact);
88  
89          final Path viewPath = ResourceUtil.getViewTemplatePath(themeName);
90          closeQuietly(viewPath);
91          final Path imagePath = ResourceUtil.getImagePath(themeName);
92          closeQuietly(imagePath);
93          final Path cssPath = ResourceUtil.getCssPath(themeName);
94          closeQuietly(cssPath);
95          final Path jsPath = ResourceUtil.getJavaScriptPath(themeName);
96          closeQuietly(jsPath);
97      }
98  
99      protected String getThemeName(final Artifact artifact) {
100         final String themeName = artifact.getName().substring(ArtifactType.THEME.getId().length() + 1);
101         if (StringUtil.isBlank(themeName)) {
102             throw new ThemeException("Theme name is empty: " + artifact);
103         }
104         return themeName;
105     }
106 
107     protected void closeQuietly(final Path dir) {
108         if (Files.notExists(dir)) {
109             if (logger.isDebugEnabled()) {
110                 logger.debug("{} does not exists.", dir);
111             }
112             return;
113         }
114         try (Stream<Path> walk = Files.walk(dir, FileVisitOption.FOLLOW_LINKS)) {
115             walk.sorted(Comparator.reverseOrder()).forEach(f -> {
116                 if (logger.isDebugEnabled()) {
117                     logger.debug("Deleting {}", f);
118                 }
119                 try {
120                     Files.delete(f);
121                 } catch (final IOException e) {
122                     logger.warn("Failed to delete {}", f, e);
123                 }
124             });
125             Files.deleteIfExists(dir);
126         } catch (final IOException e) {
127             logger.warn("Failed to delete {}", dir, e);
128         }
129     }
130 
131     protected Path getJarFile(final Artifact artifact) {
132         final Path jarPath = ResourceUtil.getPluginPath(artifact.getFileName());
133         if (!Files.exists(jarPath)) {
134             throw new ThemeException(artifact.getFileName() + " does not exist.");
135         }
136         return jarPath;
137     }
138 
139 }