Skip to content

Commit f81924f

Browse files
committed
new: reworked Plugin classloader system
1 parent 46179cb commit f81924f

File tree

10 files changed

+392
-128
lines changed

10 files changed

+392
-128
lines changed
Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package org.lowcoder.infra.event;
22

3-
import java.lang.reflect.Field;
43
import java.util.HashMap;
54
import java.util.Map;
65

@@ -15,12 +14,9 @@ public abstract class AbstractEvent implements LowcoderEvent
1514
{
1615
protected final String orgId;
1716
protected final String userId;
18-
protected final String sessionHash;
19-
protected final Boolean isAnonymous;
20-
private final String ipAddress;
21-
protected Map<String, Object> details;
17+
protected Map<String, String> details;
2218

23-
public Map<String, Object> details()
19+
public Map<String, String> details()
2420
{
2521
return this.details;
2622
}
@@ -37,20 +33,4 @@ public B detail(String name, String value)
3733
return self();
3834
}
3935
}
40-
41-
public void populateDetails() {
42-
if (details == null) {
43-
details = new HashMap<>();
44-
}
45-
for(Field f : getClass().getDeclaredFields()){
46-
Object value = null;
47-
try {
48-
f.setAccessible(Boolean.TRUE);
49-
value = f.get(this);
50-
details.put(f.getName(), value);
51-
} catch (Exception e) {
52-
}
53-
54-
}
55-
}
5636
}

server/api-service/lowcoder-infra/src/main/java/org/lowcoder/infra/serverlog/ServerLogService.java

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import org.apache.commons.collections4.CollectionUtils;
1010
import org.lowcoder.infra.event.SystemCommonEvent;
1111
import org.lowcoder.infra.perf.PerfHelper;
12-
import org.lowcoder.plugin.events.ServerLogEvent;
1312
import org.springframework.beans.factory.annotation.Autowired;
1413
import org.springframework.context.ApplicationEventPublisher;
1514
import org.springframework.scheduling.annotation.Scheduled;
@@ -47,13 +46,11 @@ private void scheduledInsert() {
4746
.subscribe(result -> {
4847
int count = result.size();
4948
perfHelper.count(SERVER_LOG_BATCH_INSERT, Tags.of("size", String.valueOf(result.size())));
50-
publishServerLogEvent(count);
49+
applicationEventPublisher.publishEvent(SystemCommonEvent.builder()
50+
.apiCalls(count)
51+
.detail("apiCalls", Integer.toString(count))
52+
.build()
53+
);
5154
});
5255
}
53-
54-
private void publishServerLogEvent(int count) {
55-
ServerLogEvent event = new ServerLogEvent();
56-
event.setApiCallsCount(count);
57-
applicationEventPublisher.publishEvent(event);
58-
}
5956
}

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/framework/configuration/PluginConfiguration.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@
2020
@Configuration
2121
public class PluginConfiguration
2222
{
23-
private final ApplicationContext applicationContext;
24-
private final PluginLoader pluginLoader;
25-
26-
public LowcoderPluginManager lowcoderPluginManager()
27-
{
28-
return new LowcoderPluginManager(applicationContext, pluginLoader);
29-
}
23+
// private final ApplicationContext applicationContext;
24+
// private final PluginLoader pluginLoader;
25+
//
26+
// public LowcoderPluginManager lowcoderPluginManager()
27+
// {
28+
// return new LowcoderPluginManager(applicationContext, pluginLoader);
29+
// }
3030

3131
@SuppressWarnings("unchecked")
3232
@Bean

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/framework/plugin/LowcoderPluginManager.java

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,21 @@
1818

1919
import org.apache.commons.collections4.CollectionUtils;
2020
import org.apache.commons.lang3.StringUtils;
21-
import org.lowcoder.plugin.EndpointExtension;
22-
import org.lowcoder.plugin.LowcoderPlugin;
23-
import org.lowcoder.plugin.PluginEndpoint;
21+
import org.lowcoder.api.framework.plugin.data.PluginServerRequest;
22+
import org.lowcoder.plugin.api.EndpointExtension;
23+
import org.lowcoder.plugin.api.LowcoderPlugin;
24+
import org.lowcoder.plugin.api.LowcoderServices;
25+
import org.lowcoder.plugin.api.PluginEndpoint;
26+
import org.lowcoder.plugin.api.data.EndpointRequest;
27+
import org.lowcoder.plugin.api.data.EndpointResponse;
2428
import org.lowcoder.sdk.exception.BaseException;
25-
import org.springframework.context.ApplicationContext;
2629
import org.springframework.core.ResolvableType;
30+
import org.springframework.http.ResponseCookie;
2731
import org.springframework.stereotype.Component;
2832
import org.springframework.web.reactive.function.server.RequestPredicate;
2933
import org.springframework.web.reactive.function.server.RouterFunction;
30-
import org.springframework.web.reactive.function.server.ServerRequest;
3134
import org.springframework.web.reactive.function.server.ServerResponse;
35+
import org.springframework.web.reactive.function.server.ServerResponse.BodyBuilder;
3236

3337
import jakarta.annotation.PostConstruct;
3438
import jakarta.annotation.PreDestroy;
@@ -41,7 +45,7 @@
4145
@Slf4j
4246
public class LowcoderPluginManager
4347
{
44-
private final ApplicationContext applicationContext;
48+
private final LowcoderServices lowcoderServices;
4549
private final PluginLoader pluginLoader;
4650

4751
private Map<String, LowcoderPlugin> plugins = new LinkedHashMap<>();
@@ -56,7 +60,7 @@ private void loadPlugins()
5660

5761
for (LowcoderPlugin plugin : sorted)
5862
{
59-
if (plugin.load(applicationContext))
63+
if (plugin.load(lowcoderServices))
6064
{
6165
log.info("Plugin [{}] loaded successfully.", plugin.pluginId());
6266
registerEndpoints(plugin);
@@ -136,7 +140,6 @@ private void registerEndpoints(LowcoderPlugin plugin)
136140
}
137141
}
138142

139-
@SuppressWarnings("unchecked")
140143
private void registerEndpointHandler(LowcoderPlugin plugin, PluginEndpoint endpoint, Method handler)
141144
{
142145
if (handler.isAnnotationPresent(EndpointExtension.class))
@@ -149,7 +152,8 @@ private void registerEndpointHandler(LowcoderPlugin plugin, PluginEndpoint endpo
149152
Mono<ServerResponse> result = null;
150153
try
151154
{
152-
result = (Mono<ServerResponse>)handler.invoke(endpoint, req);
155+
EndpointResponse response = (EndpointResponse)handler.invoke(endpoint, PluginServerRequest.fromServerRequest(req));
156+
result = createServerResponse(response);
153157
}
154158
catch (IllegalAccessException | InvocationTargetException cause)
155159
{
@@ -167,16 +171,49 @@ private void registerEndpointHandler(LowcoderPlugin plugin, PluginEndpoint endpo
167171
}
168172
}
169173

174+
private Mono<ServerResponse> createServerResponse(EndpointResponse pluginResponse)
175+
{
176+
/** Create response with given status **/
177+
BodyBuilder builder = ServerResponse.status(pluginResponse.statusCode());
178+
179+
/** Set response headers **/
180+
if (pluginResponse.headers() != null && !pluginResponse.headers().isEmpty())
181+
{
182+
pluginResponse.headers().entrySet()
183+
.forEach(entry -> {
184+
builder.header(entry.getKey(), entry.getValue().toArray(new String[] {}));
185+
});
186+
187+
}
188+
189+
/** Set cookies if available **/
190+
if (pluginResponse.cookies() != null && !pluginResponse.cookies().isEmpty())
191+
{
192+
pluginResponse.cookies().values()
193+
.forEach(cookies -> {
194+
cookies.forEach(cookie -> {
195+
builder.cookie(ResponseCookie.from(cookie.getKey(), cookie.getValue()).build());
196+
});
197+
198+
});
199+
}
200+
201+
/** Set response body if available **/
202+
if (pluginResponse.body() != null)
203+
{
204+
return builder.bodyValue(pluginResponse.body());
205+
}
206+
207+
return builder.build();
208+
}
170209

171210
private boolean checkHandlerMethod(Method method)
172211
{
173212
ResolvableType returnType = ResolvableType.forMethodReturnType(method);
174-
175-
return (returnType.getRawClass().isAssignableFrom(Mono.class)
176-
&& returnType.getGenerics().length == 1
177-
&& returnType.getGeneric(0).isAssignableFrom(ServerResponse.class)
213+
214+
return (returnType.getRawClass().isAssignableFrom(EndpointResponse.class)
178215
&& method.getParameterCount() == 1
179-
&& method.getParameterTypes()[0].isAssignableFrom(ServerRequest.class)
216+
&& method.getParameterTypes()[0].isAssignableFrom(EndpointRequest.class)
180217
);
181218
}
182219

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/framework/plugin/PathBasedPluginLoader.java

Lines changed: 13 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,17 @@
11
package org.lowcoder.api.framework.plugin;
22

33
import java.io.IOException;
4-
import java.net.URL;
5-
import java.net.URLClassLoader;
64
import java.nio.file.Files;
75
import java.nio.file.Path;
86
import java.util.ArrayList;
7+
import java.util.Iterator;
98
import java.util.List;
10-
import java.util.Set;
9+
import java.util.ServiceLoader;
1110

1211
import org.apache.commons.collections4.CollectionUtils;
1312
import org.apache.commons.lang3.StringUtils;
14-
import org.lowcoder.plugin.LowcoderPlugin;
13+
import org.lowcoder.plugin.api.LowcoderPlugin;
1514
import org.lowcoder.sdk.config.CommonConfig;
16-
import org.reflections.Reflections;
17-
import org.reflections.scanners.SubTypesScanner;
18-
import org.reflections.scanners.TypeAnnotationsScanner;
19-
import org.reflections.util.ClasspathHelper;
20-
import org.reflections.util.ConfigurationBuilder;
21-
import org.springframework.beans.factory.BeanClassLoaderAware;
2215
import org.springframework.boot.system.ApplicationHome;
2316
import org.springframework.stereotype.Component;
2417

@@ -28,12 +21,10 @@
2821
@Slf4j
2922
@RequiredArgsConstructor
3023
@Component
31-
public class PathBasedPluginLoader implements PluginLoader, BeanClassLoaderAware
24+
public class PathBasedPluginLoader implements PluginLoader
3225
{
3326
private final CommonConfig common;
3427
private final ApplicationHome applicationHome;
35-
36-
private ClassLoader beanClassLoader;
3728

3829
@Override
3930
public List<LowcoderPlugin> loadPlugins()
@@ -58,7 +49,6 @@ public List<LowcoderPlugin> loadPlugins()
5849
{
5950
for (LowcoderPlugin plugin : loadedPlugins)
6051
{
61-
log.debug(" - loaded plugin: {} :: {}", plugin.pluginId(), plugin.description());
6252
plugins.add(plugin);
6353
}
6454
}
@@ -104,38 +94,26 @@ protected List<String> findPluginCandidates(Path pluginsDir)
10494
return pluginCandidates;
10595
}
10696

107-
protected List<LowcoderPlugin> loadPluginCandidates(String pluginsDir)
97+
protected List<LowcoderPlugin> loadPluginCandidates(String pluginJar)
10898
{
10999
List<LowcoderPlugin> pluginCandidates = new ArrayList<>();
110100

111-
URLClassLoader testClassLoader = null;
112-
101+
PluginJarClassLoader pluginClassLoader = null;
113102
try
114103
{
115-
testClassLoader = URLClassLoader.newInstance(new URL[] {
116-
Path.of(pluginsDir).toUri().toURL()
117-
}, beanClassLoader);
118-
119-
Reflections reflections = new Reflections(new ConfigurationBuilder()
120-
.addClassLoader(testClassLoader)
121-
.addUrls(ClasspathHelper.forClassLoader(testClassLoader))
122-
.setScanners(new SubTypesScanner(false), new TypeAnnotationsScanner())
123-
);
104+
pluginClassLoader = new PluginJarClassLoader(getClass().getClassLoader(), Path.of(pluginJar));
124105

125-
Set<Class<? extends LowcoderPlugin>> found = reflections.getSubTypesOf(LowcoderPlugin.class);
126-
for (Class<? extends LowcoderPlugin> pluginClass : found)
106+
107+
ServiceLoader<LowcoderPlugin> pluginServices = ServiceLoader.load(LowcoderPlugin.class, pluginClassLoader);
108+
if (pluginServices != null )
127109
{
128-
log.debug(" - found plugin: {}", pluginClass.getName());
129-
try
110+
Iterator<LowcoderPlugin> pluginIterator = pluginServices.iterator();
111+
while(pluginIterator.hasNext())
130112
{
131-
LowcoderPlugin plugin = pluginClass.getConstructor().newInstance();
113+
LowcoderPlugin plugin = pluginIterator.next();
132114
log.debug(" - loaded plugin: {} - {}", plugin.pluginId(), plugin.description());
133115
pluginCandidates.add(plugin);
134116
}
135-
catch(Throwable loadFail)
136-
{
137-
log.error(" - error loading plugin: {}!", pluginClass.getName(), loadFail);
138-
}
139117
}
140118
}
141119
catch(Throwable cause)
@@ -160,11 +138,4 @@ private Path getAbsoluteNormalizedPath(String path)
160138

161139
return null;
162140
}
163-
164-
165-
@Override
166-
public void setBeanClassLoader(ClassLoader classLoader)
167-
{
168-
this.beanClassLoader = classLoader;
169-
}
170141
}

0 commit comments

Comments
 (0)