1212import  java .io .IOException ;
1313import  java .nio .file .Files ;
1414import  java .nio .file .Path ;
15- import  java .util .ArrayList ;
16- import  java .util .Iterator ;
17- import  java .util .List ;
18- import  java .util .ServiceLoader ;
15+ import  java .util .*;
1916
2017@ Slf4j 
2118@ RequiredArgsConstructor 
2219@ Component 
23- public  class  PathBasedPluginLoader  implements  PluginLoader  
24- {
20+ public  class  PathBasedPluginLoader  implements  PluginLoader  {
2521private  final  CommonConfig  common ;
2622private  final  ApplicationHome  applicationHome ;
27- 
23+ 
24+ // Cache for plugin JAR paths to avoid redundant filesystem scans 
25+ private  static  final  Map <String , List <String >> cachedPluginJars  = new  HashMap <>();
26+ 
2827@ Override 
29- public  List <LowcoderPlugin > loadPlugins () 
30- {
28+ public  List <LowcoderPlugin > loadPlugins () {
3129List <LowcoderPlugin > plugins  = new  ArrayList <>();
32- 
30+ 
31+ // Find plugin JARs using caching 
3332List <String > pluginJars  = findPluginsJars ();
34- if  (pluginJars .isEmpty ())
35- { 
33+ if  (pluginJars .isEmpty ()) { 
34+ log . debug ( "No plugin JARs found." ); 
3635return  plugins ;
3736}
3837
39- for  ( String   pluginJar  :  pluginJars ) 
40- {
38+ // Load plugins from JARs 
39+ pluginJars . parallelStream (). forEach ( pluginJar  ->  {
4140log .debug ("Inspecting plugin jar candidate: {}" , pluginJar );
4241List <LowcoderPlugin > loadedPlugins  = loadPluginCandidates (pluginJar );
43- if  (loadedPlugins .isEmpty ())
44- {
42+ if  (loadedPlugins .isEmpty ()) {
4543log .debug (" - no plugins found in the jar file" );
44+ } else  {
45+ synchronized  (plugins ) {
46+ plugins .addAll (loadedPlugins );
47+ }
4648}
47- else 
48- {
49- for  (LowcoderPlugin  plugin  : loadedPlugins )
50- {
51- plugins .add (plugin );
52- }
53- }
54- }
55- 
49+ });
50+ 
5651return  plugins ;
5752}
58- 
59- protected  List <String > findPluginsJars () 
60- {
53+ 
54+ protected  List <String > findPluginsJars () {
55+ String  cacheKey  = common .getPluginDirs ().toString ();
56+ 
57+ // Use cached JAR paths if available 
58+ if  (cachedPluginJars .containsKey (cacheKey )) {
59+ log .debug ("Using cached plugin jar candidates for key: {}" , cacheKey );
60+ return  cachedPluginJars .get (cacheKey );
61+ }
62+ 
6163List <String > candidates  = new  ArrayList <>();
62- if  (CollectionUtils .isNotEmpty (common .getPluginDirs ()))
63- {
64- for  (String  pluginDir  : common .getPluginDirs ())
65- {
64+ if  (CollectionUtils .isNotEmpty (common .getPluginDirs ())) {
65+ for  (String  pluginDir  : common .getPluginDirs ()) {
6666final  Path  pluginPath  = getAbsoluteNormalizedPath (pluginDir );
67- if  (pluginPath  != null )
68- {
67+ if  (pluginPath  != null ) {
6968candidates .addAll (findPluginCandidates (pluginPath ));
7069}
7170}
7271}
73- 
72+ 
73+ // Cache the results 
74+ cachedPluginJars .put (cacheKey , candidates );
7475return  candidates ;
7576}
7677
77- 
78- protected  List <String > findPluginCandidates (Path  pluginsDir )
79- {
80- List <String > pluginCandidates  = new  ArrayList <>();
81- try 
82- {
83- Files .walk (pluginsDir )
84-  .filter (Files ::isRegularFile )
85-  .filter (path  -> StringUtils .endsWithIgnoreCase (path .toAbsolutePath ().toString (), ".jar" ))
86-  .forEach (path  -> pluginCandidates .add (path .toString ()));
87- }
88- catch (IOException  cause )
89- {
78+ protected  List <String > findPluginCandidates (Path  pluginsDir ) {
79+ try  {
80+ return  Files .walk (pluginsDir )
81+ .filter (Files ::isRegularFile )
82+ .filter (path  -> StringUtils .endsWithIgnoreCase (path .toAbsolutePath ().toString (), ".jar" ))
83+ .map (Path ::toString )
84+ .toList (); // Use Java 16+ `toList()` for better performance 
85+ } catch  (IOException  cause ) {
9086log .error ("Error walking plugin folder! - {}" , cause .getMessage ());
87+ return  Collections .emptyList ();
9188}
92- 
93- return  pluginCandidates ;
9489}
95- 
96- protected  List <LowcoderPlugin > loadPluginCandidates (String  pluginJar )
97- {
90+ 
91+ protected  List <LowcoderPlugin > loadPluginCandidates (String  pluginJar ) {
9892List <LowcoderPlugin > pluginCandidates  = new  ArrayList <>();
9993
100- try 
101- {
94+ try  {
10295Path  pluginPath  = Path .of (pluginJar );
10396PluginClassLoader  pluginClassLoader  = new  PluginClassLoader (pluginPath .getFileName ().toString (), pluginPath );
10497
10598ServiceLoader <LowcoderPlugin > pluginServices  = ServiceLoader .load (LowcoderPlugin .class , pluginClassLoader );
106- if  (pluginServices  != null  )
107- {
108- Iterator <LowcoderPlugin > pluginIterator  = pluginServices .iterator ();
109- while (pluginIterator .hasNext ())
110- {
111- LowcoderPlugin  plugin  = pluginIterator .next ();
99+ if  (pluginServices  != null ) {
100+ for  (LowcoderPlugin  plugin  : pluginServices ) {
112101log .debug (" - loaded plugin: {} - {}" , plugin .pluginId (), plugin .description ());
113102pluginCandidates .add (plugin );
114103}
115104}
116- }
117- catch (Throwable  cause )
118- {
105+ } catch  (Throwable  cause ) {
119106log .warn ("Error loading plugin!" , cause );
120107}
121- 
108+ 
122109return  pluginCandidates ;
123110}
124- 
125- private  Path  getAbsoluteNormalizedPath (String  path )
126- {
127- if  (StringUtils .isNotBlank (path ))
128- {
111+ 
112+ private  Path  getAbsoluteNormalizedPath (String  path ) {
113+ if  (StringUtils .isNotBlank (path )) {
129114Path  absPath  = Path .of (path );
130- if  (!absPath .isAbsolute ())
131- {
115+ if  (!absPath .isAbsolute ()) {
132116absPath  = Path .of (applicationHome .getDir ().getAbsolutePath (), absPath .toString ());
133117}
134118return  absPath .normalize ().toAbsolutePath ();
135119}
136- 
137120return  null ;
138121}
139- }
122+ }
0 commit comments