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.util;
17  
18  import java.util.ArrayList;
19  import java.util.HashMap;
20  import java.util.List;
21  import java.util.Map;
22  import java.util.function.Consumer;
23  
24  import org.apache.logging.log4j.LogManager;
25  import org.apache.logging.log4j.Logger;
26  import org.codelibs.core.crypto.CachedCipher;
27  import org.codelibs.core.misc.DynamicProperties;
28  import org.codelibs.fess.api.WebApiManagerFactory;
29  import org.codelibs.fess.auth.AuthenticationManager;
30  import org.codelibs.fess.chat.ChatClient;
31  import org.codelibs.fess.chat.ChatSessionManager;
32  import org.codelibs.fess.cors.CorsHandlerFactory;
33  import org.codelibs.fess.crawler.client.CrawlerClientCreator;
34  import org.codelibs.fess.crawler.client.CrawlerClientFactory;
35  import org.codelibs.fess.crawler.entity.OpenSearchAccessResult;
36  import org.codelibs.fess.crawler.extractor.ExtractorFactory;
37  import org.codelibs.fess.crawler.service.DataService;
38  import org.codelibs.fess.dict.DictionaryManager;
39  import org.codelibs.fess.ds.DataStoreFactory;
40  import org.codelibs.fess.exception.ContainerNotAvailableException;
41  import org.codelibs.fess.helper.AccessTokenHelper;
42  import org.codelibs.fess.helper.ActivityHelper;
43  import org.codelibs.fess.helper.CrawlerStatsHelper;
44  import org.codelibs.fess.helper.CoordinatorHelper;
45  import org.codelibs.fess.helper.CrawlingConfigHelper;
46  import org.codelibs.fess.helper.CrawlingInfoHelper;
47  import org.codelibs.fess.helper.CurlHelper;
48  import org.codelibs.fess.helper.DocumentHelper;
49  import org.codelibs.fess.helper.DuplicateHostHelper;
50  import org.codelibs.fess.helper.FileTypeHelper;
51  import org.codelibs.fess.helper.IndexingHelper;
52  import org.codelibs.fess.helper.IntervalControlHelper;
53  import org.codelibs.fess.helper.JobHelper;
54  import org.codelibs.fess.helper.KeyMatchHelper;
55  import org.codelibs.fess.helper.LabelTypeHelper;
56  import org.codelibs.fess.helper.LanguageHelper;
57  import org.codelibs.fess.helper.LogNotificationHelper;
58  import org.codelibs.fess.helper.MarkdownRenderer;
59  import org.codelibs.fess.helper.NotificationHelper;
60  import org.codelibs.fess.helper.PasswordHashHelper;
61  import org.codelibs.fess.helper.PathMappingHelper;
62  import org.codelibs.fess.helper.PermissionHelper;
63  import org.codelibs.fess.helper.PluginHelper;
64  import org.codelibs.fess.helper.PopularWordHelper;
65  import org.codelibs.fess.helper.ProcessHelper;
66  import org.codelibs.fess.helper.ProtocolHelper;
67  import org.codelibs.fess.helper.QueryHelper;
68  import org.codelibs.fess.helper.RateLimitHelper;
69  import org.codelibs.fess.helper.RelatedContentHelper;
70  import org.codelibs.fess.helper.RelatedQueryHelper;
71  import org.codelibs.fess.helper.RoleQueryHelper;
72  import org.codelibs.fess.helper.SambaHelper;
73  import org.codelibs.fess.helper.SearchHelper;
74  import org.codelibs.fess.helper.SearchLogHelper;
75  import org.codelibs.fess.helper.SuggestHelper;
76  import org.codelibs.fess.helper.SystemHelper;
77  import org.codelibs.fess.helper.ThemeHelper;
78  import org.codelibs.fess.helper.UserAgentHelper;
79  import org.codelibs.fess.helper.UserInfoHelper;
80  import org.codelibs.fess.helper.ViewHelper;
81  import org.codelibs.fess.helper.VirtualHostHelper;
82  import org.codelibs.fess.indexer.IndexUpdater;
83  import org.codelibs.fess.ingest.IngestFactory;
84  import org.codelibs.fess.job.JobExecutor;
85  import org.codelibs.fess.ldap.LdapManager;
86  import org.codelibs.fess.mylasta.direction.FessConfig;
87  import org.codelibs.fess.mylasta.direction.FessProp;
88  import org.codelibs.fess.opensearch.client.SearchEngineClient;
89  import org.codelibs.fess.query.QueryFieldConfig;
90  import org.codelibs.fess.query.QueryProcessor;
91  import org.codelibs.fess.query.parser.QueryParser;
92  import org.codelibs.fess.rank.fusion.RankFusionProcessor;
93  import org.codelibs.fess.script.ScriptEngineFactory;
94  import org.codelibs.fess.sso.SsoManager;
95  import org.codelibs.fess.thumbnail.ThumbnailManager;
96  import org.lastaflute.core.message.MessageManager;
97  import org.lastaflute.core.security.PrimaryCipher;
98  import org.lastaflute.di.core.SingletonLaContainer;
99  import org.lastaflute.di.core.exception.AutoBindingFailureException;
100 import org.lastaflute.di.core.exception.ComponentNotFoundException;
101 import org.lastaflute.di.core.factory.SingletonLaContainerFactory;
102 import org.lastaflute.di.core.smart.hot.HotdeployUtil;
103 import org.lastaflute.job.JobManager;
104 import org.lastaflute.web.servlet.request.RequestManager;
105 import org.lastaflute.web.servlet.request.ResponseManager;
106 
107 /**
108  * Utility class for accessing system components and dependencies.
109  * Provides centralized access to various helpers, managers, and services throughout the Fess application.
110  */
111 public final class ComponentUtil {
112 
113     private static final Logger logger = LogManager.getLogger(ComponentUtil.class);
114 
115     /** Component map for storing component instances. */
116     private static Map<String, Object> componentMap = new HashMap<>();
117 
118     private static final String SCRIPT_ENGINE_FACTORY = "scriptEngineFactory";
119 
120     private static final String INGEST_FACTORY = "ingestFactory";
121 
122     private static final String NOTIFICATION_HELPER = "notificationHelper";
123 
124     private static final String LOG_NOTIFICATION_HELPER = "logNotificationHelper";
125 
126     private static final String SEARCH_HELPER = "searchHelper";
127 
128     private static final String THEME_HELPER = "themeHelper";
129 
130     private static final String PLUGIN_HELPER = "pluginHelper";
131 
132     private static final String LANGUAGE_HELPER = "languageHelper";
133 
134     private static final String CURL_HELPER = "curlHelper";
135 
136     private static final String COORDINATOR_HELPER = "coordinatorHelper";
137 
138     private static final String QUERY_STRING_BUILDER = "queryStringBuilder";
139 
140     private static final String ACCESS_TOKEN_HELPER = "accessTokenHelper";
141 
142     private static final String RATE_LIMIT_HELPER = "rateLimitHelper";
143 
144     private static final String AUTHENTICATION_MANAGER = "authenticationManager";
145 
146     private static final String THUMBNAIL_MANAGER = "thumbnailManager";
147 
148     private static final String SSO_MANAGER = "ssoManager";
149 
150     private static final String PERMISSION_HELPER = "permissionHelper";
151 
152     private static final String PASSWORD_HASH_HELPER = "passwordHashHelper";
153 
154     private static final String QUERY_PARSER = "queryParser";
155 
156     private static final String DOCUMENT_HELPER = "documentHelper";
157 
158     private static final String ACTIVITY_HELPER = "activityHelper";
159 
160     private static final String LDAP_MANAGER = "ldapManager";
161 
162     private static final String ROLE_QUERY_HELPER = "roleQueryHelper";
163 
164     private static final String SUGGEST_HELPER = "suggestHelper";
165 
166     private static final String SEARCH_ENGINE_CLIENT = "searchEngineClient";
167 
168     private static final String DICTIONARY_MANAGER = "dictionaryManager";
169 
170     private static final String DATA_SERVICE = "dataService";
171 
172     private static final String MESSAGE_MANAGER = "messageManager";
173 
174     private static final String INDEX_UPDATER = "indexUpdater";
175 
176     private static final String FILE_TYPE_HELPER = "fileTypeHelper";
177 
178     private static final String EXTRACTOR_FACTORY = "extractorFactory";
179 
180     private static final String INTERVAL_CONTROL_HELPER = "intervalControlHelper";
181 
182     private static final String DATA_STORE_FACTORY = "dataStoreFactory";
183 
184     private static final String USER_AGENT_HELPER = "userAgentHelper";
185 
186     private static final String USER_INFO_HELPER = "userInfoHelper";
187 
188     private static final String WEB_API_MANAGER_FACTORY = "webApiManagerFactory";
189 
190     private static final String PROCESS_HELPER = "processHelper";
191 
192     private static final String JOB_HELPER = "jobHelper";
193 
194     private static final String DUPLICATE_HOST_HELPER = "duplicateHostHelper";
195 
196     private static final String PATH_MAPPING_HELPER = "pathMappingHelper";
197 
198     private static final String POPULAR_WORD_HELPER = "popularWordHelper";
199 
200     private static final String CRAWLING_INFO_HELPER = "crawlingInfoHelper";
201 
202     private static final String CRAWLING_CONFIG_HELPER = "crawlingConfigHelper";
203 
204     private static final String SEARCH_LOG_HELPER = "searchLogHelper";
205 
206     private static final String LABEL_TYPE_HELPER = "labelTypeHelper";
207 
208     private static final String QUERY_HELPER = "queryHelper";
209 
210     private static final String QUERY_FIELD_CONFIG = "queryFieldConfig";
211 
212     private static final String QUERY_PROCESSOR = "queryProcessor";
213 
214     private static final String SAMBA_HELPER = "sambaHelper";
215 
216     private static final String VIEW_HELPER = "viewHelper";
217 
218     private static final String SYSTEM_HELPER = "systemHelper";
219 
220     private static final String CRAWLER_PROPERTIES = "systemProperties";
221 
222     private static final String JOB_EXECUTOR_SUFFIX = "JobExecutor";
223 
224     private static final String KEY_MATCH_HELPER = "keyMatchHelper";
225 
226     private static final String INDEXING_HELPER = "indexingHelper";
227 
228     private static final String VIRTUAL_HOST_HELPER = "virtualHostHelper";
229 
230     private static final String RELATED_CONTENT_HELPER = "relatedContentHelper";
231 
232     private static final String RELATED_QUERY_HELPER = "relatedQueryHelper";
233 
234     private static final String CRAWLER_STATS_HELPER = "crawlerStatsHelper";
235 
236     private static final String CORS_HANDLER_FACTORY = "corsHandlerFactory";
237 
238     private static final String RANK_FUSION_PROCESSOR = "rankFusionProcessor";
239 
240     private static final String PROTOCOL_HELPER = "protocolHelper";
241 
242     private static final String CHAT_SESSION_MANAGER = "chatSessionManager";
243 
244     private static final String CHAT_CLIENT = "chatClient";
245 
246     private static final String MARKDOWN_RENDERER = "markdownRenderer";
247 
248     private static IndexingHelper indexingHelper;
249 
250     private static CrawlingConfigHelper crawlingConfigHelper;
251 
252     private static SystemHelper systemHelper;
253 
254     private static FessConfig fessConfig;
255 
256     /** List of initialization processes to run after container initialization. */
257     private static List<Runnable> initProcesses = new ArrayList<>();
258 
259     /**
260      * Private constructor to prevent instantiation.
261      */
262     private ComponentUtil() {
263     }
264 
265     /**
266      * Processes a runnable after container initialization.
267      * @param process The process to run after container init.
268      */
269     public static void processAfterContainerInit(final Runnable process) {
270         if (available()) {
271             process.run();
272         } else {
273             initProcesses.add(process);
274         }
275     }
276 
277     /**
278      * Executes all initialization processes.
279      * @param action The action to perform on each initialization process.
280      */
281     public static void doInitProcesses(final Consumer<? super Runnable> action) {
282         try {
283             initProcesses.forEach(action);
284         } finally {
285             initProcesses.clear();
286         }
287     }
288 
289     /**
290      * Gets a cached cipher by name.
291      * @param cipherName The cipher name.
292      * @return The cached cipher.
293      */
294     public static CachedCipher getCipher(final String cipherName) {
295         return getComponent(cipherName);
296     }
297 
298     /**
299      * Gets the system properties.
300      * @return The dynamic properties.
301      */
302     public static DynamicProperties getSystemProperties() {
303         return getComponent(CRAWLER_PROPERTIES);
304     }
305 
306     /**
307      * Gets the system helper component.
308      * @return The system helper.
309      */
310     public static SystemHelper getSystemHelper() {
311         if (systemHelper == null || HotdeployUtil.isHotdeploy()) {
312             systemHelper = getComponent(SYSTEM_HELPER);
313         }
314         return systemHelper;
315     }
316 
317     /**
318      * Gets the view helper component.
319      * @return The view helper.
320      */
321     public static ViewHelper getViewHelper() {
322         return getComponent(VIEW_HELPER);
323     }
324 
325     /**
326      * Gets the Samba helper component.
327      * @return The Samba helper.
328      */
329     public static SambaHelper getSambaHelper() {
330         return getComponent(SAMBA_HELPER);
331     }
332 
333     /**
334      * Gets the query helper component.
335      * @return The query helper.
336      */
337     public static QueryHelper getQueryHelper() {
338         return getComponent(QUERY_HELPER);
339     }
340 
341     /**
342      * Gets the query field configuration.
343      * @return The query field config.
344      */
345     public static QueryFieldConfig getQueryFieldConfig() {
346         return getComponent(QUERY_FIELD_CONFIG);
347     }
348 
349     /**
350      * Gets the query processor component.
351      * @return The query processor.
352      */
353     public static QueryProcessor getQueryProcessor() {
354         return getComponent(QUERY_PROCESSOR);
355     }
356 
357     /**
358      * Gets the label type helper component.
359      * @return The label type helper.
360      */
361     public static LabelTypeHelper getLabelTypeHelper() {
362         return getComponent(LABEL_TYPE_HELPER);
363     }
364 
365     /**
366      * Gets the search log helper component.
367      * @return The search log helper.
368      */
369     public static SearchLogHelper getSearchLogHelper() {
370         return getComponent(SEARCH_LOG_HELPER);
371     }
372 
373     /**
374      * Gets the crawling configuration helper component.
375      * @return The crawling config helper.
376      */
377     public static CrawlingConfigHelper getCrawlingConfigHelper() {
378         if (crawlingConfigHelper == null || HotdeployUtil.isHotdeploy()) {
379             crawlingConfigHelper = getComponent(CRAWLING_CONFIG_HELPER);
380         }
381         return crawlingConfigHelper;
382     }
383 
384     /**
385      * Gets the crawling info helper component.
386      * @return The crawling info helper.
387      */
388     public static CrawlingInfoHelper getCrawlingInfoHelper() {
389         return getComponent(CRAWLING_INFO_HELPER);
390     }
391 
392     /**
393      * Gets the popular word helper component.
394      * @return The popular word helper.
395      */
396     public static PopularWordHelper getPopularWordHelper() {
397         return getComponent(POPULAR_WORD_HELPER);
398     }
399 
400     /**
401      * Gets the path mapping helper component.
402      * @return The path mapping helper.
403      */
404     public static PathMappingHelper getPathMappingHelper() {
405         return getComponent(PATH_MAPPING_HELPER);
406     }
407 
408     /**
409      * Gets the duplicate host helper component.
410      * @return The duplicate host helper.
411      */
412     public static DuplicateHostHelper getDuplicateHostHelper() {
413         return getComponent(DUPLICATE_HOST_HELPER);
414     }
415 
416     /**
417      * Gets the process helper component.
418      * @return The process helper.
419      */
420     public static ProcessHelper getProcessHelper() {
421         return getComponent(PROCESS_HELPER);
422     }
423 
424     /**
425      * Gets the job helper component.
426      * @return The job helper.
427      */
428     public static JobHelper getJobHelper() {
429         return getComponent(JOB_HELPER);
430     }
431 
432     /**
433      * Gets the web API manager factory component.
434      * @return The web API manager factory.
435      */
436     public static WebApiManagerFactory getWebApiManagerFactory() {
437         return getComponent(WEB_API_MANAGER_FACTORY);
438     }
439 
440     /**
441      * Gets the user agent helper component.
442      * @return The user agent helper.
443      */
444     public static UserAgentHelper getUserAgentHelper() {
445         return getComponent(USER_AGENT_HELPER);
446     }
447 
448     /**
449      * Gets the data store factory component.
450      * @return The data store factory.
451      */
452     public static DataStoreFactory getDataStoreFactory() {
453         return getComponent(DATA_STORE_FACTORY);
454     }
455 
456     /**
457      * Gets the interval control helper component.
458      * @return The interval control helper.
459      */
460     public static IntervalControlHelper getIntervalControlHelper() {
461         return getComponent(INTERVAL_CONTROL_HELPER);
462     }
463 
464     /**
465      * Gets the extractor factory component.
466      * @return The extractor factory.
467      */
468     public static ExtractorFactory getExtractorFactory() {
469         return getComponent(EXTRACTOR_FACTORY);
470     }
471 
472     /**
473      * Gets a job executor by name.
474      * @param name The name of the job executor.
475      * @return The job executor instance.
476      */
477     public static JobExecutor getJobExecutor(final String name) {
478         if (name.endsWith(JOB_EXECUTOR_SUFFIX)) {
479             return getComponent(name);
480         }
481         return getComponent("script" + JOB_EXECUTOR_SUFFIX);
482     }
483 
484     /**
485      * Gets the file type helper component.
486      * @return The file type helper.
487      */
488     public static FileTypeHelper getFileTypeHelper() {
489         return getComponent(FILE_TYPE_HELPER);
490     }
491 
492     /**
493      * Gets the index updater component.
494      * @return The index updater.
495      */
496     public static IndexUpdater getIndexUpdater() {
497         return getComponent(INDEX_UPDATER);
498     }
499 
500     /**
501      * Gets the key match helper component.
502      * @return The key match helper.
503      */
504     public static KeyMatchHelper getKeyMatchHelper() {
505         return getComponent(KEY_MATCH_HELPER);
506     }
507 
508     /**
509      * Gets the indexing helper component.
510      * @return The indexing helper.
511      */
512     public static IndexingHelper getIndexingHelper() {
513         if (indexingHelper == null || HotdeployUtil.isHotdeploy()) {
514             indexingHelper = getComponent(INDEXING_HELPER);
515         }
516         return indexingHelper;
517     }
518 
519     /**
520      * Gets the user info helper component.
521      * @return The user info helper.
522      */
523     public static UserInfoHelper getUserInfoHelper() {
524         return getComponent(USER_INFO_HELPER);
525     }
526 
527     /**
528      * Gets the message manager component.
529      * @return The message manager.
530      */
531     public static MessageManager getMessageManager() {
532         return getComponent(MESSAGE_MANAGER);
533     }
534 
535     /**
536      * Gets the dictionary manager component.
537      * @return The dictionary manager.
538      */
539     public static DictionaryManager getDictionaryManager() {
540         return getComponent(DICTIONARY_MANAGER);
541     }
542 
543     /**
544      * Gets the data service component.
545      * @return The data service.
546      */
547     public static DataService<OpenSearchAccessResult> getDataService() {
548         return getComponent(DATA_SERVICE);
549     }
550 
551     /**
552      * Gets the search engine client component.
553      * @return The search engine client.
554      */
555     public static SearchEngineClient getSearchEngineClient() {
556         return getComponent(SEARCH_ENGINE_CLIENT);
557     }
558 
559     /**
560      * Gets the Fess configuration component.
561      * @return The Fess config.
562      */
563     public static FessConfig getFessConfig() {
564         if (fessConfig != null) {
565             return fessConfig;
566         }
567         fessConfig = getComponent(FessConfig.class);
568         return fessConfig;
569     }
570 
571     /**
572      * Gets the suggest helper component.
573      * @return The suggest helper.
574      */
575     public static SuggestHelper getSuggestHelper() {
576         return getComponent(SUGGEST_HELPER);
577     }
578 
579     /**
580      * Gets the role query helper component.
581      * @return The role query helper.
582      */
583     public static RoleQueryHelper getRoleQueryHelper() {
584         return getComponent(ROLE_QUERY_HELPER);
585     }
586 
587     /**
588      * Gets the LDAP manager component.
589      * @return The LDAP manager.
590      */
591     public static LdapManager getLdapManager() {
592         return getComponent(LDAP_MANAGER);
593     }
594 
595     /**
596      * Gets the activity helper component.
597      * @return The activity helper.
598      */
599     public static ActivityHelper getActivityHelper() {
600         return getComponent(ACTIVITY_HELPER);
601     }
602 
603     /**
604      * Gets the request manager component.
605      * @return The request manager.
606      */
607     public static RequestManager getRequestManager() {
608         return getComponent(RequestManager.class);
609     }
610 
611     /**
612      * Gets the response manager component.
613      * @return The response manager.
614      */
615     public static ResponseManager getResponseManager() {
616         return getComponent(ResponseManager.class);
617     }
618 
619     /**
620      * Gets the job manager component.
621      * @return The job manager.
622      */
623     public static JobManager getJobManager() {
624         return getComponent(JobManager.class);
625     }
626 
627     /**
628      * Gets the document helper component.
629      * @return The document helper.
630      */
631     public static DocumentHelper getDocumentHelper() {
632         return getComponent(DOCUMENT_HELPER);
633     }
634 
635     /**
636      * Gets the query parser component.
637      * @return The query parser.
638      */
639     public static QueryParser getQueryParser() {
640         return getComponent(QUERY_PARSER);
641     }
642 
643     /**
644      * Gets the permission helper component.
645      * @return The permission helper.
646      */
647     public static PermissionHelper getPermissionHelper() {
648         return getComponent(PERMISSION_HELPER);
649     }
650 
651     /**
652      * Gets the password hash helper component.
653      * @return The password hash helper.
654      */
655     public static PasswordHashHelper getPasswordHashHelper() {
656         return getComponent(PASSWORD_HASH_HELPER);
657     }
658 
659     /**
660      * Gets the SSO manager component.
661      * @return The SSO manager.
662      */
663     public static SsoManager getSsoManager() {
664         return getComponent(SSO_MANAGER);
665     }
666 
667     /**
668      * Gets the thumbnail manager component.
669      * @return The thumbnail manager.
670      */
671     public static ThumbnailManager getThumbnailManager() {
672         return getComponent(THUMBNAIL_MANAGER);
673     }
674 
675     /**
676      * Gets the authentication manager component.
677      * @return The authentication manager.
678      */
679     public static AuthenticationManager getAuthenticationManager() {
680         return getComponent(AUTHENTICATION_MANAGER);
681     }
682 
683     /**
684      * Gets the primary cipher component.
685      * @return The primary cipher.
686      */
687     public static PrimaryCipher getPrimaryCipher() {
688         return getComponent(PrimaryCipher.class);
689     }
690 
691     /**
692      * Gets the crawler client factory component.
693      * @return The crawler client factory.
694      */
695     public static CrawlerClientFactory getCrawlerClientFactory() {
696         return getComponent(CrawlerClientFactory.class);
697     }
698 
699     /**
700      * Gets the crawler client creator component.
701      * @return The crawler client creator.
702      */
703     public static CrawlerClientCreator getCrawlerClientCreator() {
704         return getComponent(CrawlerClientCreator.class);
705     }
706 
707     /**
708      * Gets the related query helper component.
709      * @return The related query helper.
710      */
711     public static RelatedQueryHelper getRelatedQueryHelper() {
712         return getComponent(RELATED_QUERY_HELPER);
713     }
714 
715     /**
716      * Gets the related content helper component.
717      * @return The related content helper.
718      */
719     public static RelatedContentHelper getRelatedContentHelper() {
720         return getComponent(RELATED_CONTENT_HELPER);
721     }
722 
723     /**
724      * Gets the virtual host helper component.
725      * @return The virtual host helper.
726      */
727     public static VirtualHostHelper getVirtualHostHelper() {
728         return getComponent(VIRTUAL_HOST_HELPER);
729     }
730 
731     /**
732      * Gets the access token helper component.
733      * @return The access token helper.
734      */
735     public static AccessTokenHelper getAccessTokenHelper() {
736         return getComponent(ACCESS_TOKEN_HELPER);
737     }
738 
739     /**
740      * Gets the rate limit helper component.
741      * @return The rate limit helper.
742      */
743     public static RateLimitHelper getRateLimitHelper() {
744         return getComponent(RATE_LIMIT_HELPER);
745     }
746 
747     /**
748      * Gets the query string builder component.
749      * @return The query string builder.
750      */
751     public static QueryStringBuilder getQueryStringBuilder() {
752         return getComponent(QUERY_STRING_BUILDER);
753     }
754 
755     /**
756      * Gets the curl helper component.
757      * @return The curl helper.
758      */
759     public static CurlHelper getCurlHelper() {
760         return getComponent(CURL_HELPER);
761     }
762 
763     /**
764      * Gets the coordinator helper component.
765      * @return The coordinator helper.
766      */
767     public static CoordinatorHelper getCoordinatorHelper() {
768         return getComponent(COORDINATOR_HELPER);
769     }
770 
771     /**
772      * Gets the language helper component.
773      * @return The language helper.
774      */
775     public static LanguageHelper getLanguageHelper() {
776         return getComponent(LANGUAGE_HELPER);
777     }
778 
779     /**
780      * Gets the plugin helper component.
781      * @return The plugin helper.
782      */
783     public static PluginHelper getPluginHelper() {
784         return getComponent(PLUGIN_HELPER);
785     }
786 
787     /**
788      * Gets the theme helper component.
789      * @return The theme helper.
790      */
791     public static ThemeHelper getThemeHelper() {
792         return getComponent(THEME_HELPER);
793     }
794 
795     /**
796      * Gets the search helper component.
797      * @return The search helper.
798      */
799     public static SearchHelper getSearchHelper() {
800         return getComponent(SEARCH_HELPER);
801     }
802 
803     /**
804      * Gets the notification helper component.
805      * @return The notification helper.
806      */
807     public static NotificationHelper getNotificationHelper() {
808         return getComponent(NOTIFICATION_HELPER);
809     }
810 
811     /**
812      * Gets the log notification helper component.
813      * @return The log notification helper.
814      */
815     public static LogNotificationHelper getLogNotificationHelper() {
816         return getComponent(LOG_NOTIFICATION_HELPER);
817     }
818 
819     /**
820      * Gets the ingest factory component.
821      * @return The ingest factory.
822      */
823     public static IngestFactory getIngestFactory() {
824         return getComponent(INGEST_FACTORY);
825     }
826 
827     /**
828      * Gets the script engine factory component.
829      * @return The script engine factory.
830      */
831     public static ScriptEngineFactory getScriptEngineFactory() {
832         return getComponent(SCRIPT_ENGINE_FACTORY);
833     }
834 
835     /**
836      * Gets the crawler stats helper component.
837      * @return The crawler stats helper.
838      */
839     public static CrawlerStatsHelper getCrawlerStatsHelper() {
840         return getComponent(CRAWLER_STATS_HELPER);
841     }
842 
843     /**
844      * Gets the CORS handler factory component.
845      * @return The CORS handler factory.
846      */
847     public static CorsHandlerFactory getCorsHandlerFactory() {
848         return getComponent(CORS_HANDLER_FACTORY);
849     }
850 
851     /**
852      * Gets the rank fusion processor component.
853      * @return The rank fusion processor.
854      */
855     public static RankFusionProcessor getRankFusionProcessor() {
856         return getComponent(RANK_FUSION_PROCESSOR);
857     }
858 
859     /**
860      * Gets the protocol helper component.
861      * @return The protocol helper.
862      */
863     public static ProtocolHelper getProtocolHelper() {
864         return getComponent(PROTOCOL_HELPER);
865     }
866 
867     /**
868      * Gets the chat session manager component.
869      * @return The chat session manager.
870      */
871     public static ChatSessionManager getChatSessionManager() {
872         return getComponent(CHAT_SESSION_MANAGER);
873     }
874 
875     /**
876      * Gets the chat client component.
877      * @return The chat client.
878      */
879     public static ChatClient getChatClient() {
880         return getComponent(CHAT_CLIENT);
881     }
882 
883     /**
884      * Gets the markdown renderer component.
885      * @return The markdown renderer.
886      */
887     public static MarkdownRenderer getMarkdownRenderer() {
888         return getComponent(MARKDOWN_RENDERER);
889     }
890 
891     /**
892      * Gets a component by its class type.
893      * @param <T> The type of the component.
894      * @param clazz The class of the component to retrieve.
895      * @return The component instance.
896      */
897     @SuppressWarnings("unchecked")
898     public static <T> T getComponent(final Class<T> clazz) {
899         try {
900             return SingletonLaContainer.getComponent(clazz);
901         } catch (final NullPointerException e) {
902             if (logger.isDebugEnabled()) {
903                 throw new ContainerNotAvailableException(clazz.getCanonicalName(), e);
904             }
905             throw new ContainerNotAvailableException(clazz.getCanonicalName());
906         } catch (final ComponentNotFoundException | AutoBindingFailureException e) {
907             if (componentMap.containsKey(clazz.getCanonicalName())) {
908                 return (T) componentMap.get(clazz.getCanonicalName());
909             }
910             throw e;
911         }
912     }
913 
914     /**
915      * Gets a component by its name.
916      * @param <T> The type of the component.
917      * @param componentName The name of the component to retrieve.
918      * @return The component instance.
919      */
920     @SuppressWarnings("unchecked")
921     public static <T> T getComponent(final String componentName) {
922         try {
923             return SingletonLaContainer.getComponent(componentName);
924         } catch (final NullPointerException e) {
925             if (logger.isDebugEnabled()) {
926                 throw new ContainerNotAvailableException(componentName, e);
927             }
928             throw new ContainerNotAvailableException(componentName);
929         } catch (final ComponentNotFoundException | AutoBindingFailureException e) {
930             if (componentMap.containsKey(componentName)) {
931                 return (T) componentMap.get(componentName);
932             }
933             throw e;
934         }
935     }
936 
937     /**
938      * Checks if a component is available.
939      * @param componentKey The key of the component to check.
940      * @return True if the component is available, false otherwise.
941      */
942     public static boolean hasComponent(final String componentKey) {
943         if (SingletonLaContainerFactory.getContainer().hasComponentDef(componentKey)) {
944             return true;
945         }
946         return componentMap.containsKey(componentKey);
947     }
948 
949     /**
950      * Checks if query parser is available.
951      * @return True if query parser is available, false otherwise.
952      */
953     public static boolean hasQueryParser() {
954         return hasComponent(QUERY_PARSER);
955     }
956 
957     /**
958      * Checks if the request manager is available in the container.
959      * Useful for callers that may run outside a web-request scope (e.g. unit
960      * tests or background jobs) and need to avoid {@link ComponentNotFoundException}
961      * or {@link NullPointerException} from {@link #getRequestManager()}.
962      * @return True if the request manager component is registered, false otherwise.
963      */
964     public static boolean hasRequestManager() {
965         try {
966             return SingletonLaContainerFactory.getContainer().hasComponentDef(RequestManager.class);
967         } catch (final NullPointerException e) {
968             return false;
969         }
970     }
971 
972     /**
973      * Checks if view helper is available.
974      * @return True if view helper is available, false otherwise.
975      */
976     public static boolean hasViewHelper() {
977         return hasComponent(VIEW_HELPER);
978     }
979 
980     /**
981      * Checks if query helper is available.
982      * @return True if query helper is available, false otherwise.
983      */
984     public static boolean hasQueryHelper() {
985         return hasComponent(QUERY_HELPER);
986     }
987 
988     /**
989      * Checks if popular word helper is available.
990      * @return True if popular word helper is available, false otherwise.
991      */
992     public static boolean hasPopularWordHelper() {
993         return hasComponent(POPULAR_WORD_HELPER);
994     }
995 
996     /**
997      * Checks if related query helper is available.
998      * @return True if related query helper is available, false otherwise.
999      */
1000     public static boolean hasRelatedQueryHelper() {
1001         return hasComponent(RELATED_QUERY_HELPER);
1002     }
1003 
1004     /**
1005      * Checks if ingest factory is available.
1006      * @return True if ingest factory is available, false otherwise.
1007      */
1008     public static boolean hasIngestFactory() {
1009         return hasComponent(INGEST_FACTORY);
1010     }
1011 
1012     /**
1013      * Checks if the container is available.
1014      * @return True if the container is available, false otherwise.
1015      */
1016     public static boolean available() {
1017         try {
1018             return SingletonLaContainer.getComponent(SYSTEM_HELPER) != null;
1019         } catch (final Exception e) {
1020             // ignore
1021         }
1022         return false;
1023     }
1024 
1025     /**
1026      * For test purpose only.
1027      *
1028      * @param fessConfig fessConfig instance
1029      */
1030     public static void setFessConfig(final FessConfig fessConfig) {
1031         ComponentUtil.fessConfig = fessConfig;
1032         if (fessConfig == null) {
1033             systemHelper = null;
1034             FessProp.propMap.clear();
1035             componentMap.clear();
1036         }
1037     }
1038 
1039     /**
1040      * Registers a component instance with a name.
1041      * @param instance The component instance to register.
1042      * @param name The name to register the component under.
1043      */
1044     public static void register(final Object instance, final String name) {
1045         componentMap.put(name, instance);
1046     }
1047 
1048 }