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.systeminfo;
17  
18  import java.util.ArrayList;
19  import java.util.HashMap;
20  import java.util.List;
21  import java.util.Map;
22  
23  import org.codelibs.core.lang.StringUtil;
24  import org.codelibs.core.misc.DynamicProperties;
25  import org.codelibs.fess.Constants;
26  import org.codelibs.fess.annotation.Secured;
27  import org.codelibs.fess.app.web.base.FessAdminAction;
28  import org.codelibs.fess.mylasta.direction.FessConfig;
29  import org.codelibs.fess.util.ComponentUtil;
30  import org.codelibs.fess.util.RenderDataUtil;
31  import org.lastaflute.core.direction.ObjectiveConfig;
32  import org.lastaflute.web.Execute;
33  import org.lastaflute.web.response.HtmlResponse;
34  import org.lastaflute.web.response.render.RenderData;
35  import org.lastaflute.web.ruts.process.ActionRuntime;
36  
37  import jakarta.annotation.Resource;
38  
39  /**
40   * Admin action for System Info.
41   *
42   */
43  public class AdminSysteminfoAction extends FessAdminAction {
44  
45      /**
46       * Default constructor.
47       */
48      public AdminSysteminfoAction() {
49          super();
50      }
51  
52      /** Role name for admin system info operations */
53      public static final String ROLE = "admin-systeminfo";
54  
55      private static final String MASKED_VALUE = "XXXXXXXX";
56  
57      // ===================================================================================
58      //                                                                           Attribute
59      //                                                                           =========
60      /** System properties for retrieving configuration information. */
61      @Resource
62      protected DynamicProperties systemProperties;
63  
64      private static final String[] bugReportLabels =
65              { "file.separator", "file.encoding", "java.runtime.version", "java.vm.info", "java.vm.name", "java.vm.vendor",
66                      "java.vm.version", "os.arch", "os.name", "os.version", "user.country", "user.language", "user.timezone" };
67  
68      // ===================================================================================
69      //                                                                               Hook
70      //                                                                              ======
71      @Override
72      protected void setupHtmlData(final ActionRuntime runtime) {
73          super.setupHtmlData(runtime);
74          runtime.registerData("helpLink", systemHelper.getHelpLink(fessConfig.getOnlineHelpNameSysteminfo()));
75      }
76  
77      @Override
78      protected String getActionRole() {
79          return ROLE;
80      }
81  
82      // ===================================================================================
83      //                                                                              Index
84      //                                                                      ==============
85      /**
86       * Displays the system information page with environment, properties, and configuration details.
87       *
88       * @return HTML response for the system info page
89       */
90      @Execute
91      @Secured({ ROLE, ROLE + VIEW })
92      public HtmlResponse index() {
93          return asHtml(path_AdminSysteminfo_AdminSysteminfoJsp).renderWith(data -> {
94              registerEnvItems(data);
95              registerPropItems(data);
96              registerFessPropItems(data);
97              registerBugReportItems(data);
98          });
99      }
100 
101     // ===================================================================================
102     //                                                                        Assist Logic
103     //                                                                        ============
104 
105     /**
106      * Registers environment variables for rendering.
107      *
108      * @param data the render data to populate
109      */
110     protected void registerEnvItems(final RenderData data) {
111         RenderDataUtil.register(data, "envItems", getEnvItems());
112     }
113 
114     /**
115      * Registers system properties for rendering.
116      *
117      * @param data the render data to populate
118      */
119     protected void registerPropItems(final RenderData data) {
120         RenderDataUtil.register(data, "propItems", getPropItems());
121     }
122 
123     /**
124      * Registers Fess-specific properties for rendering.
125      *
126      * @param data the render data to populate
127      */
128     protected void registerFessPropItems(final RenderData data) {
129         RenderDataUtil.register(data, "fessPropItems", getFessPropItems(fessConfig));
130     }
131 
132     /**
133      * Registers bug report items for rendering.
134      *
135      * @param data the render data to populate
136      */
137     protected void registerBugReportItems(final RenderData data) {
138         RenderDataUtil.register(data, "bugReportItems", getBugReportItems());
139     }
140 
141     /**
142      * Gets a list of environment variables as key-value pairs.
143      *
144      * @return list of environment variable items
145      */
146     public static List<Map<String, String>> getEnvItems() {
147         final List<Map<String, String>> itemList = new ArrayList<>();
148         for (final Map.Entry<String, String> entry : System.getenv().entrySet()) {
149             itemList.add(createItem(entry.getKey(), entry.getValue()));
150         }
151         return itemList;
152     }
153 
154     /**
155      * Gets a list of system properties as key-value pairs.
156      *
157      * @return list of system property items
158      */
159     public static List<Map<String, String>> getPropItems() {
160         final List<Map<String, String>> itemList = new ArrayList<>();
161         for (final Map.Entry<Object, Object> entry : System.getProperties().entrySet()) {
162             itemList.add(createItem(entry.getKey(), entry.getValue()));
163         }
164         return itemList;
165     }
166 
167     /**
168      * Gets a list of Fess-specific configuration properties as key-value pairs.
169      *
170      * @param fessConfig the Fess configuration object
171      * @return list of Fess property items
172      */
173     public static List<Map<String, String>> getFessPropItems(final FessConfig fessConfig) {
174         final List<Map<String, String>> itemList = new ArrayList<>();
175         ComponentUtil.getSystemProperties().entrySet().stream().forEach(e -> {
176             final String k = e.getKey().toString();
177             final String value;
178             if (isMaskedValue(k)) {
179                 value = MASKED_VALUE;
180             } else {
181                 value = e.getValue().toString();
182             }
183             itemList.add(createItem(k, value));
184         });
185         if (fessConfig instanceof final ObjectiveConfig config) {
186             config.keySet().stream().forEach(k -> {
187                 final String value;
188                 if (isMaskedValue(k)) {
189                     value = MASKED_VALUE;
190                 } else {
191                     value = config.get(k);
192                 }
193                 itemList.add(createItem(k, value));
194             });
195         }
196         return itemList;
197     }
198 
199     /**
200      * Checks if a property value should be masked for security reasons.
201      *
202      * @param key the property key to check
203      * @return true if the value should be masked, false otherwise
204      */
205     protected static boolean isMaskedValue(final String key) {
206         return "http.proxy.password".equals(key) //
207                 || "ldap.admin.security.credentials".equals(key) //
208                 || "spnego.preauth.password".equals(key) //
209                 || "app.cipher.key".equals(key) //
210                 || "oic.client.id".equals(key) //
211                 || "oic.client.secret".equals(key);
212     }
213 
214     /**
215      * Gets a list of items relevant for bug reports.
216      *
217      * @return list of bug report items
218      */
219     public static List<Map<String, String>> getBugReportItems() {
220         final List<Map<String, String>> itemList = new ArrayList<>();
221         for (final String label : bugReportLabels) {
222             itemList.add(createPropItem(label));
223         }
224 
225         final DynamicProperties systemProperties = ComponentUtil.getSystemProperties();
226         for (final Map.Entry<Object, Object> entry : systemProperties.entrySet()) {
227             if (isBugReportTarget(entry.getKey())) {
228                 itemList.add(createItem(entry.getKey(), entry.getValue()));
229             }
230         }
231 
232         return itemList;
233     }
234 
235     /**
236      * Checks if a property should be included in bug reports.
237      *
238      * @param key the property key to check
239      * @return true if the property should be included, false otherwise
240      */
241     private static boolean isBugReportTarget(final Object key) {
242         if ("snapshot.path".equals(key) || "label.value".equals(key)) {
243             return false;
244         }
245         return true;
246     }
247 
248     /**
249      * Creates a property item from a system property key.
250      *
251      * @param key the property key
252      * @return map containing the key-value pair
253      */
254     protected static Map<String, String> createPropItem(final String key) {
255         return createItem(key, System.getProperty(key));
256     }
257 
258     /**
259      * Creates a key-value item map for display.
260      *
261      * @param label the item label
262      * @param value the item value
263      * @return map containing the formatted key-value pair
264      */
265     protected static Map<String, String> createItem(final Object label, final Object value) {
266         final Map<String, String> map = new HashMap<>(2);
267         map.put(Constants.ITEM_LABEL, label != null ? label.toString() : StringUtil.EMPTY);
268         map.put(Constants.ITEM_VALUE, value != null ? value.toString() : StringUtil.EMPTY);
269         return map;
270     }
271 
272 }