1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.codelibs.fess.app.web.admin.plugin;
17
18 import java.io.File;
19 import java.io.FileOutputStream;
20 import java.io.InputStream;
21 import java.io.OutputStream;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.stream.Collectors;
28
29 import org.apache.logging.log4j.LogManager;
30 import org.apache.logging.log4j.Logger;
31 import org.codelibs.core.io.CopyUtil;
32 import org.codelibs.fess.annotation.Secured;
33 import org.codelibs.fess.app.web.base.FessAdminAction;
34 import org.codelibs.fess.helper.PluginHelper;
35 import org.codelibs.fess.helper.PluginHelper.Artifact;
36 import org.codelibs.fess.helper.PluginHelper.ArtifactType;
37 import org.codelibs.fess.util.ComponentUtil;
38 import org.codelibs.fess.util.RenderDataUtil;
39 import org.lastaflute.web.Execute;
40 import org.lastaflute.web.response.HtmlResponse;
41 import org.lastaflute.web.ruts.process.ActionRuntime;
42 import org.lastaflute.web.validation.exception.ValidationErrorException;
43
44
45
46
47
48
49 public class AdminPluginAction extends FessAdminAction {
50
51
52
53
54 public AdminPluginAction() {
55 super();
56 }
57
58
59
60
61 public static final String ROLE = "admin-plugin";
62
63 private static final Logger logger = LogManager.getLogger(AdminPluginAction.class);
64
65 private static final String UPLOAD = "upload";
66
67 @Override
68 protected void setupHtmlData(final ActionRuntime runtime) {
69 super.setupHtmlData(runtime);
70 runtime.registerData("helpLink", systemHelper.getHelpLink(fessConfig.getOnlineHelpNamePlugin()));
71 }
72
73
74
75
76
77
78 @Override
79 protected String getActionRole() {
80 return ROLE;
81 }
82
83
84
85
86
87
88 @Execute
89 @Secured({ ROLE, ROLE + VIEW })
90 public HtmlResponse index() {
91 saveToken();
92 return asListHtml();
93 }
94
95
96
97
98
99
100
101 @Execute
102 @Secured({ ROLE })
103 public HtmlResponse delete(final DeleteForm form) {
104 validate(form, messages -> {}, () -> asHtml(path_AdminPlugin_AdminPluginJsp));
105 verifyToken(() -> asHtml(path_AdminPlugin_AdminPluginJsp));
106 final Artifact artifact = new Artifact(form.name, form.version, null);
107 deleteArtifact(artifact);
108 saveInfo(messages -> messages.addSuccessDeletePlugin(GLOBAL, artifact.getFileName()));
109 return redirect(getClass());
110 }
111
112
113
114
115
116
117
118 @Execute
119 @Secured({ ROLE })
120 public HtmlResponse install(final InstallForm form) {
121 validate(form, messages -> {}, () -> asHtml(path_AdminPlugin_AdminPluginInstallpluginJsp));
122 verifyToken(() -> asHtml(path_AdminPlugin_AdminPluginInstallpluginJsp));
123 try {
124 if (UPLOAD.equals(form.id)) {
125 if (form.jarFile == null) {
126 throwValidationError(messages -> messages.addErrorsPluginFileIsNotFound(GLOBAL, form.id), this::asListHtml);
127 }
128 if (!form.jarFile.getFileName().endsWith(".jar")) {
129 throwValidationError(messages -> messages.addErrorsFileIsNotSupported(GLOBAL, form.jarFile.getFileName()),
130 this::asListHtml);
131 }
132 final String filename = form.jarFile.getFileName();
133 final File tempFile = ComponentUtil.getSystemHelper().createTempFile("tmp-adminplugin-", ".jar");
134 try (final InputStream is = form.jarFile.getInputStream(); final OutputStream os = new FileOutputStream(tempFile)) {
135 CopyUtil.copy(is, os);
136 } catch (final Exception e) {
137 if (tempFile.exists() && !tempFile.delete()) {
138 logger.warn("Failed to delete {}.", tempFile.getAbsolutePath());
139 }
140 logger.debug("Failed to copy {}", filename, e);
141 throwValidationError(messages -> messages.addErrorsFailedToInstallPlugin(GLOBAL, filename), this::asListHtml);
142 }
143 new Thread(() -> {
144 try {
145 final PluginHelper pluginHelper = ComponentUtil.getPluginHelper();
146 final Artifact artifact =
147 pluginHelper.getArtifactFromFileName(ArtifactType.UNKNOWN, filename, tempFile.getAbsolutePath());
148 pluginHelper.installArtifact(artifact);
149 } catch (final Exception e) {
150 logger.warn("Failed to install {}", filename, e);
151 } finally {
152 if (tempFile.exists() && !tempFile.delete()) {
153 logger.warn("Failed to delete {}.", tempFile.getAbsolutePath());
154 }
155 }
156 }).start();
157 saveInfo(messages -> messages.addSuccessInstallPlugin(GLOBAL, form.jarFile.getFileName()));
158 } else {
159 final Artifact artifact = getArtifactFromInstallForm(form);
160 if (artifact == null) {
161 throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, form.id), this::asListHtml);
162 }
163 installArtifact(artifact);
164 saveInfo(messages -> messages.addSuccessInstallPlugin(GLOBAL, artifact.getFileName()));
165 }
166 } catch (final ValidationErrorException e) {
167 throw e;
168 } catch (final Exception e) {
169 throwValidationError(messages -> messages.addErrorsFailedToInstallPlugin(GLOBAL, form.id), this::asListHtml);
170 }
171 return redirect(getClass());
172 }
173
174
175
176
177
178
179 @Execute
180 @Secured({ ROLE })
181 public HtmlResponse installplugin() {
182 saveToken();
183 return asHtml(path_AdminPlugin_AdminPluginInstallpluginJsp).renderWith(data -> {
184 final List<Map<String, String>> result = new ArrayList<>();
185 final Map<String, String> map = new HashMap<>();
186 map.put("id", UPLOAD);
187 map.put("name", "");
188 map.put("version", "");
189 result.add(map);
190 try {
191 result.addAll(getAllAvailableArtifacts());
192 } catch (final Exception e) {
193 saveError(messages -> messages.addErrorsFailedToFindPlugins(GLOBAL));
194 logger.warn("Failed to access a plugin repository.", e);
195 }
196 RenderDataUtil.register(data, "availableArtifactItems", result);
197 }).useForm(InstallForm.class, op -> op.setup(form -> {}));
198 }
199
200 private HtmlResponse asListHtml() {
201 return asHtml(path_AdminPlugin_AdminPluginJsp)
202 .renderWith(data -> data.register("installedArtifactItems", getAllInstalledArtifacts()))
203 .useForm(DeleteForm.class);
204 }
205
206
207
208
209
210
211 public static List<Map<String, String>> getAllAvailableArtifacts() {
212 final PluginHelper pluginHelper = ComponentUtil.getPluginHelper();
213 final List<Map<String, String>> result = new ArrayList<>();
214 for (final PluginHelper.ArtifactType artifactType : PluginHelper.ArtifactType.values()) {
215 result.addAll(Arrays.stream(pluginHelper.getAvailableArtifacts(artifactType))
216 .map(AdminPluginAction::beanToMap)
217 .collect(Collectors.toList()));
218 }
219 return result;
220 }
221
222
223
224
225
226
227 public static List<Map<String, String>> getAllInstalledArtifacts() {
228 final PluginHelper pluginHelper = ComponentUtil.getPluginHelper();
229 final List<Map<String, String>> result = new ArrayList<>();
230 for (final PluginHelper.ArtifactType artifactType : PluginHelper.ArtifactType.values()) {
231 result.addAll(Arrays.stream(pluginHelper.getInstalledArtifacts(artifactType))
232 .map(AdminPluginAction::beanToMap)
233 .collect(Collectors.toList()));
234 }
235 return result;
236 }
237
238
239
240
241
242
243
244 public static Map<String, String> beanToMap(final Artifact artifact) {
245 final Map<String, String> item = new HashMap<>();
246 item.put("type", artifact.getType().getId());
247 item.put("id", artifact.getName() + ":" + artifact.getVersion());
248 item.put("name", artifact.getName());
249 item.put("version", artifact.getVersion());
250 item.put("url", artifact.getUrl());
251 return item;
252 }
253
254 private Artifact getArtifactFromInstallForm(final InstallForm form) {
255 final String[] values = form.id.split(":");
256 return ComponentUtil.getPluginHelper().getArtifact(values[0], values[1]);
257 }
258
259
260
261
262
263
264
265 public static void installArtifact(final Artifact artifact) {
266 new Thread(() -> {
267 final PluginHelper pluginHelper = ComponentUtil.getPluginHelper();
268 final Artifact[] artifacts = pluginHelper.getInstalledArtifacts(artifact.getType());
269 try {
270 pluginHelper.installArtifact(artifact);
271 } catch (final Exception e) {
272 logger.warn("Failed to install {}", artifact.getFileName(), e);
273 }
274 for (final Artifact a : artifacts) {
275 if (a.getName().equals(artifact.getName()) && !a.getVersion().equals(artifact.getVersion())) {
276 try {
277 pluginHelper.deleteInstalledArtifact(a);
278 } catch (final Exception e) {
279 logger.warn("Failed to delete {}", a.getFileName(), e);
280 }
281 }
282 }
283 }).start();
284 }
285
286
287
288
289
290
291 public static void deleteArtifact(final Artifact artifact) {
292 new Thread(() -> {
293 try {
294 ComponentUtil.getPluginHelper().deleteInstalledArtifact(artifact);
295 } catch (final Exception e) {
296 logger.warn("Failed to delete {}", artifact.getFileName(), e);
297 }
298 }).start();
299 }
300 }