24
24
25
25
package org .sourcelab .kafka .webview .ui .configuration ;
26
26
27
+ import com .fasterxml .jackson .core .JsonProcessingException ;
28
+ import com .fasterxml .jackson .databind .ObjectMapper ;
29
+
30
+ import java .io .File ;
31
+
32
+ import java .net .MalformedURLException ;
33
+ import java .net .URL ;
34
+ import java .net .URLClassLoader ;
35
+
27
36
import org .apache .kafka .common .serialization .ByteArrayDeserializer ;
28
37
import org .apache .kafka .common .serialization .BytesDeserializer ;
29
38
import org .apache .kafka .common .serialization .DoubleDeserializer ;
43
52
import org .springframework .stereotype .Component ;
44
53
45
54
import java .util .HashMap ;
55
+ import java .util .List ;
46
56
import java .util .Map ;
57
+ import java .util .ServiceLoader ;
58
+
59
+ import org .slf4j .Logger ;
60
+ import org .slf4j .LoggerFactory ;
61
+
62
+ import org .sourcelab .kafka .webview .ui .plugin .deserializer .DeserializerDiscoveryService ;
63
+ import org .sourcelab .kafka .webview .ui .plugin .deserializer .DeserializerInformation ;
64
+ import org .sourcelab .kafka .webview .ui .model .MessageFormatType ;
47
65
48
66
/**
49
67
* Called on startup to ensure we have sane default data loaded.
50
68
*/
51
69
@ Component
52
70
public final class DataLoaderConfig implements ApplicationRunner {
53
71
72
+ private static final Logger logger = LoggerFactory .getLogger (DataLoaderConfig .class );
73
+
74
+ private final AppProperties appProperties ;
54
75
private final MessageFormatRepository messageFormatRepository ;
55
76
private final UserRepository userRepository ;
77
+ private final ObjectMapper mapper ;
56
78
57
79
/**
58
80
* Constructor.
59
81
*/
60
82
@ Autowired
61
- private DataLoaderConfig (final MessageFormatRepository messageFormatRepository , final UserRepository userRepository ) {
83
+ private DataLoaderConfig (
84
+ final AppProperties appProperties ,
85
+ final MessageFormatRepository messageFormatRepository ,
86
+ final UserRepository userRepository ,
87
+ final ObjectMapper mapper ) {
88
+ this .appProperties = appProperties ;
62
89
this .messageFormatRepository = messageFormatRepository ;
63
90
this .userRepository = userRepository ;
91
+ this .mapper = mapper ;
64
92
}
65
93
66
94
/**
@@ -69,6 +97,7 @@ private DataLoaderConfig(final MessageFormatRepository messageFormatRepository,
69
97
private void createData () {
70
98
createDefaultUser ();
71
99
createDefaultMessageFormats ();
100
+ discoverDeserializers ();
72
101
}
73
102
74
103
/**
@@ -112,11 +141,66 @@ private void createDefaultMessageFormats() {
112
141
messageFormat .setName (entry .getKey ());
113
142
messageFormat .setClasspath (entry .getValue ());
114
143
messageFormat .setJar ("n/a" );
115
- messageFormat .setDefaultFormat ( true );
144
+ messageFormat .setMessageFormatType ( MessageFormatType . DEFAULT );
116
145
messageFormatRepository .save (messageFormat );
117
146
}
118
147
}
119
148
149
+ private void discoverDeserializers () {
150
+ final File deserializerPath = new File (appProperties .getDeserializerPath ());
151
+
152
+ // Check preconditions
153
+ if (!deserializerPath .exists ()) {
154
+ logger .warn ("Directory {} doesn't exists." , deserializerPath );
155
+ return ;
156
+ }
157
+ if (!deserializerPath .isDirectory ()) {
158
+ logger .error ("{} is not a directory." , deserializerPath );
159
+ return ;
160
+ }
161
+
162
+ File [] jars = deserializerPath .listFiles ((File dir , String name ) -> name .endsWith (".jar" ));
163
+ logger .info ("Analyse {} for deserializer" , (Object ) jars );
164
+ for (File jar : jars ) {
165
+ try {
166
+ URL jarUrl = jar .toURI ().toURL ();
167
+ ClassLoader cl = new URLClassLoader (new URL []{jarUrl }, getClass ().getClassLoader ());
168
+ ServiceLoader <DeserializerDiscoveryService > services = ServiceLoader .load (DeserializerDiscoveryService .class , cl );
169
+ loadDeserializers (jar , services );
170
+ } catch (MalformedURLException ex ) {
171
+ logger .error ("Failed to load {}, error: {}" , jar , ex .getMessage ());
172
+ }
173
+ }
174
+ }
175
+
176
+ private void loadDeserializers (File jar , ServiceLoader <DeserializerDiscoveryService > services ) {
177
+ for (DeserializerDiscoveryService service : services ) {
178
+ List <DeserializerInformation > deserializersInformation = service .getDeserializersInformation ();
179
+ for (DeserializerInformation deserializerInformation : deserializersInformation ) {
180
+ try {
181
+ MessageFormat messageFormat = messageFormatRepository .findByName (deserializerInformation .getName ());
182
+ if (messageFormat == null ) {
183
+ messageFormat = new MessageFormat ();
184
+ } else if (MessageFormatType .AUTOCONF != messageFormat .getMessageFormatType ()) {
185
+ logger .error ("Try to register the formatter {} but this name is already register as a {}." ,
186
+ messageFormat .getName (), messageFormat .getMessageFormatType ());
187
+ continue ;
188
+ }
189
+ messageFormat .setName (deserializerInformation .getName ());
190
+ messageFormat .setClasspath (deserializerInformation .getClasspath ());
191
+ messageFormat .setJar (jar .getName ());
192
+ messageFormat .setMessageFormatType (MessageFormatType .AUTOCONF );
193
+ messageFormat .setOptionParameters (
194
+ mapper .writeValueAsString (deserializerInformation .getDefaultConfig ()));
195
+ messageFormatRepository .save (messageFormat );
196
+ } catch (JsonProcessingException ex ) {
197
+ logger .error ("Failed to load {}, because the default config are invalid ({})" ,
198
+ deserializerInformation .getName (), ex .getMessage ());
199
+ }
200
+ }
201
+ }
202
+ }
203
+
120
204
/**
121
205
* Run on startup.
122
206
*/
0 commit comments