View Javadoc
1   /*
2    * Copyright 2012-2025 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.app.web.admin.crawlinginfo;
17  
18  import org.apache.logging.log4j.LogManager;
19  import org.apache.logging.log4j.Logger;
20  import org.codelibs.fess.Constants;
21  import org.codelibs.fess.annotation.Secured;
22  import org.codelibs.fess.app.pager.CrawlingInfoPager;
23  import org.codelibs.fess.app.service.CrawlingInfoService;
24  import org.codelibs.fess.app.web.CrudMode;
25  import org.codelibs.fess.app.web.base.FessAdminAction;
26  import org.codelibs.fess.helper.ProcessHelper;
27  import org.codelibs.fess.util.RenderDataUtil;
28  import org.lastaflute.web.Execute;
29  import org.lastaflute.web.response.HtmlResponse;
30  import org.lastaflute.web.response.render.RenderData;
31  import org.lastaflute.web.ruts.process.ActionRuntime;
32  
33  import jakarta.annotation.Resource;
34  
35  /**
36   * Admin action for Crawling Info management.
37   *
38   */
39  public class AdminCrawlinginfoAction extends FessAdminAction {
40  
41      /**
42       * Default constructor.
43       */
44      public AdminCrawlinginfoAction() {
45          super();
46      }
47  
48      /** The role for this action. */
49      public static final String ROLE = "admin-crawlinginfo";
50  
51      private static final Logger logger = LogManager.getLogger(AdminCrawlinginfoAction.class);
52  
53      // ===================================================================================
54      //                                                                           Attribute
55      //                                                                           =========
56      @Resource
57      private CrawlingInfoService crawlingInfoService;
58      @Resource
59      private CrawlingInfoPager crawlingInfoPager;
60      /** The process helper. */
61      @Resource
62      protected ProcessHelper processHelper;
63  
64      // ===================================================================================
65      //                                                                               Hook
66      //                                                                              ======
67      @Override
68      protected void setupHtmlData(final ActionRuntime runtime) {
69          super.setupHtmlData(runtime);
70          runtime.registerData("helpLink", systemHelper.getHelpLink(fessConfig.getOnlineHelpNameCrawlinginfo()));
71      }
72  
73      @Override
74      protected String getActionRole() {
75          return ROLE;
76      }
77  
78      // ===================================================================================
79      //                                                                      Search Execute
80      //                                                                      ==============
81      /**
82       * Show the index page.
83       * @return The HTML response.
84       */
85      @Execute
86      @Secured({ ROLE, ROLE + VIEW })
87      public HtmlResponse index() {
88          saveToken();
89          return asListHtml();
90      }
91  
92      /**
93       * Show the list page.
94       * @param pageNumber The page number.
95       * @param form The search form.
96       * @return The HTML response.
97       */
98      @Execute
99      @Secured({ ROLE, ROLE + VIEW })
100     public HtmlResponse list(final Integer pageNumber, final SearchForm form) {
101         saveToken();
102         crawlingInfoPager.setCurrentPageNumber(pageNumber);
103         return asHtml(path_AdminCrawlinginfo_AdminCrawlinginfoJsp).renderWith(data -> {
104             searchPaging(data, form);
105         });
106     }
107 
108     /**
109      * Search crawling info.
110      * @param form The search form.
111      * @return The HTML response.
112      */
113     @Execute
114     @Secured({ ROLE, ROLE + VIEW })
115     public HtmlResponse search(final SearchForm form) {
116         saveToken();
117         copyBeanToBean(form, crawlingInfoPager, op -> op.exclude(Constants.PAGER_CONVERSION_RULE));
118         return asHtml(path_AdminCrawlinginfo_AdminCrawlinginfoJsp).renderWith(data -> {
119             searchPaging(data, form);
120         });
121     }
122 
123     /**
124      * Reset the search form.
125      * @param form The search form.
126      * @return The HTML response.
127      */
128     @Execute
129     @Secured({ ROLE, ROLE + VIEW })
130     public HtmlResponse reset(final SearchForm form) {
131         saveToken();
132         crawlingInfoPager.clear();
133         return asHtml(path_AdminCrawlinginfo_AdminCrawlinginfoJsp).renderWith(data -> {
134             searchPaging(data, form);
135         });
136     }
137 
138     /**
139      * Go back to the list page.
140      * @param form The search form.
141      * @return The HTML response.
142      */
143     @Execute
144     @Secured({ ROLE, ROLE + VIEW })
145     public HtmlResponse back(final SearchForm form) {
146         saveToken();
147         return asHtml(path_AdminCrawlinginfo_AdminCrawlinginfoJsp).renderWith(data -> {
148             searchPaging(data, form);
149         });
150     }
151 
152     /**
153      * Search with paging.
154      * @param data The render data.
155      * @param form The search form.
156      */
157     protected void searchPaging(final RenderData data, final SearchForm form) {
158         RenderDataUtil.register(data, "crawlingInfoItems", crawlingInfoService.getCrawlingInfoList(crawlingInfoPager)); // page navi
159 
160         // restore from pager
161         copyBeanToBean(crawlingInfoPager, form, op -> op.include("sessionId"));
162     }
163 
164     // ===================================================================================
165     //                                                                        Edit Execute
166     //                                                                        ============
167 
168     // -----------------------------------------------------
169     //                                               Details
170     //                                               -------
171     /**
172      * Show the details page.
173      * @param crudMode The CRUD mode.
174      * @param id The crawling info ID.
175      * @return The HTML response.
176      */
177     @Execute
178     @Secured({ ROLE, ROLE + VIEW })
179     public HtmlResponse details(final int crudMode, final String id) {
180         verifyCrudMode(crudMode, CrudMode.DETAILS, this::asListHtml);
181         saveToken();
182         return crawlingInfoService.getCrawlingInfo(id)
183                 .map(entity -> asHtml(path_AdminCrawlinginfo_AdminCrawlinginfoDetailsJsp).useForm(EditForm.class, op -> {
184                     op.setup(form -> {
185                         copyBeanToBean(entity, form, copyOp -> {
186                             copyOp.excludeNull();
187                         });
188                         form.crudMode = crudMode;
189                     });
190                 }).renderWith(data -> {
191                     RenderDataUtil.register(data, "crawlingInfoParamItems", crawlingInfoService.getCrawlingInfoParamList(id));
192                     RenderDataUtil.register(data, "running", processHelper.isProcessRunning(entity.getSessionId()));
193                 }))
194                 .orElseGet(() -> {
195                     throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, id), this::asListHtml);
196                     return null;
197                 });
198     }
199 
200     /**
201      * Print a thread dump.
202      * @param form The edit form.
203      * @return The HTML response.
204      */
205     @Execute
206     @Secured({ ROLE })
207     public HtmlResponse threaddump(final EditForm form) {
208         verifyCrudMode(form.crudMode, CrudMode.DETAILS, this::asListHtml);
209         validate(form, messages -> {}, this::asDetailsHtml);
210         verifyToken(this::asDetailsHtml);
211         final String id = form.id;
212         crawlingInfoService.getCrawlingInfo(id).ifPresent(entity -> {
213             try {
214                 processHelper.sendCommand(entity.getSessionId(), Constants.CRAWLER_PROCESS_COMMAND_THREAD_DUMP);
215                 saveInfo(messages -> messages.addSuccessPrintThreadDump(GLOBAL));
216             } catch (final Exception e) {
217                 logger.warn("Failed to print a thread dump.", e);
218                 throwValidationError(messages -> messages.addErrorsFailedToPrintThreadDump(GLOBAL), this::asListHtml);
219             }
220         }).orElse(() -> {
221             throwValidationError(messages -> messages.addErrorsCrudCouldNotFindCrudTable(GLOBAL, id), this::asListHtml);
222         });
223         return redirect(getClass());
224     }
225 
226     // -----------------------------------------------------
227     //                                         Actually Crud
228     //                                         -------------
229     /**
230      * Delete a crawling info.
231      * @param form The edit form.
232      * @return The HTML response.
233      */
234     @Execute
235     @Secured({ ROLE })
236     public HtmlResponse delete(final EditForm form) {
237         verifyCrudMode(form.crudMode, CrudMode.DETAILS, this::asListHtml);
238         validate(form, messages -> {}, this::asDetailsHtml);
239         verifyToken(this::asDetailsHtml);
240         final String id = form.id;
241         crawlingInfoService.getCrawlingInfo(id).alwaysPresent(entity -> {
242             crawlingInfoService.delete(entity);
243             saveInfo(messages -> messages.addSuccessCrudDeleteCrudTable(GLOBAL));
244         });
245         return redirect(getClass());
246     }
247 
248     /**
249      * Delete all crawling info.
250      * @return The HTML response.
251      */
252     @Execute
253     @Secured({ ROLE, ROLE + VIEW })
254     public HtmlResponse deleteall() {
255         verifyToken(this::asListHtml);
256         crawlingInfoService.deleteOldSessions(processHelper.getRunningSessionIdSet());
257         crawlingInfoPager.clear();
258         saveInfo(messages -> messages.addSuccessCrawlingInfoDeleteAll(GLOBAL));
259         return redirect(getClass());
260     }
261 
262     // ===================================================================================
263     //                                                                        Assist Logic
264     //                                                                        ============
265 
266     // ===================================================================================
267     //                                                                        Small Helper
268     //                                                                        ============
269     // ===================================================================================
270     //                                                                              JSP
271     //                                                                           =========
272 
273     private HtmlResponse asListHtml() {
274         return asHtml(path_AdminCrawlinginfo_AdminCrawlinginfoJsp).renderWith(data -> {
275             RenderDataUtil.register(data, "crawlingInfoItems", crawlingInfoService.getCrawlingInfoList(crawlingInfoPager)); // page navi
276         }).useForm(SearchForm.class, setup -> {
277             setup.setup(form -> {
278                 copyBeanToBean(crawlingInfoPager, form, op -> op.include("id"));
279             });
280         });
281     }
282 
283     private HtmlResponse asDetailsHtml() {
284         return asHtml(path_AdminCrawlinginfo_AdminCrawlinginfoDetailsJsp);
285     }
286 }