• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

leeonky / test-charm-java / 117

26 Feb 2025 03:01AM UTC coverage: 74.16% (+0.9%) from 73.251%
117

push

circleci

leeonky
Update version

7838 of 10569 relevant lines covered (74.16%)

0.74 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.0
/DAL-extension-inspector/src/main/java/com/github/leeonky/dal/extensions/inspector/Inspector.java
1
package com.github.leeonky.dal.extensions.inspector;
2

3
import com.github.leeonky.dal.DAL;
4
import com.github.leeonky.dal.runtime.RuntimeContextBuilder;
5
import com.github.leeonky.interpreter.InterpreterException;
6
import com.github.leeonky.util.Suppressor;
7
import de.neuland.pug4j.PugConfiguration;
8
import de.neuland.pug4j.template.TemplateLoader;
9
import io.javalin.Javalin;
10
import io.javalin.http.staticfiles.Location;
11
import io.javalin.plugin.rendering.JavalinRenderer;
12
import io.javalin.websocket.WsContext;
13

14
import java.io.IOException;
15
import java.io.InputStreamReader;
16
import java.io.Reader;
17
import java.nio.charset.StandardCharsets;
18
import java.util.*;
19
import java.util.concurrent.ConcurrentHashMap;
20
import java.util.concurrent.CountDownLatch;
21
import java.util.function.Supplier;
22
import java.util.stream.Collectors;
23

24
import static com.github.leeonky.util.function.Extension.getFirstPresent;
25
import static java.lang.Thread.currentThread;
26
import static java.util.Objects.requireNonNull;
27
import static java.util.Optional.ofNullable;
28

29
public class Inspector {
30
    private static Inspector inspector = null;
1✔
31
    private static Mode mode = null;
1✔
32
    private final Javalin javalin;
33
    private final CountDownLatch serverReadyLatch;
34
    private final Set<DAL> instances = new LinkedHashSet<>();
1✔
35
    //   TODO refactor
36
    private final Map<String, WsContext> clientConnections = new ConcurrentHashMap<>();
1✔
37
    private final Map<String, Set<String>> clientMonitors = new ConcurrentHashMap<>();
1✔
38
    private final Map<String, DalInstance> dalInstances = new ConcurrentHashMap<>();
1✔
39
    private static Supplier<Object> defaultInput = () -> null;
1✔
40

41
    public Inspector() {
1✔
42
        dalInstances.put("Try It!", new DalInstance(() -> defaultInput.get(), DAL.create(InspectorExtension.class), ""));
1✔
43

44
        PugConfiguration pugConfiguration = new PugConfiguration();
1✔
45
        pugConfiguration.setTemplateLoader(new TemplateLoader() {
1✔
46
            @Override
47
            public long getLastModified(String name) throws IOException {
48
                return -1;
1✔
49
            }
50

51
            @Override
52
            public Reader getReader(String name) throws IOException {
53
                return new InputStreamReader(requireNonNull(currentThread().getContextClassLoader().getResourceAsStream(name)),
1✔
54
                        StandardCharsets.UTF_8);
55
            }
56

57
            @Override
58
            public String getExtension() {
59
                return "pug";
×
60
            }
61

62
            @Override
63
            public String getBase() {
64
                return "";
×
65
            }
66
        });
67

68
        JavalinRenderer.register((filePath, model, context) ->
1✔
69
                pugConfiguration.renderTemplate(pugConfiguration.getTemplate("public/" + filePath), model), ".pug", ".PNG", ".Png");
1✔
70

71
        serverReadyLatch = new CountDownLatch(1);
1✔
72
        javalin = Javalin.create(config -> config.addStaticFiles("/public", Location.CLASSPATH))
1✔
73
                .events(event -> event.serverStarted(serverReadyLatch::countDown));
1✔
74
        requireNonNull(javalin.jettyServer()).setServerPort(10081);
1✔
75
        javalin.get("/", ctx -> ctx.render("/index.pug", Collections.emptyMap()));
1✔
76
        javalin.post("/api/execute", ctx -> ctx.html(execute(ctx.queryParam("name"), ctx.body())));
1✔
77
        javalin.post("/api/exchange", ctx -> exchange(ctx.queryParam("session"), ctx.body()));
1✔
78
        javalin.post("/api/release", ctx -> release(ctx.queryParam("name")));
1✔
79
        javalin.post("/api/release-all", ctx -> releaseAll());
1✔
80
        javalin.get("/api/request", ctx -> ctx.html(request(ctx.queryParam("name"))));
1✔
81
        javalin.ws("/ws/exchange", ws -> {
1✔
82
            ws.onConnect(ctx -> {
1✔
83
                clientConnections.put(ctx.getSessionId(), ctx);
1✔
84
                sendInstances(ctx);
1✔
85
            });
1✔
86
            ws.onClose(ctx -> clientConnections.remove(ctx.getSessionId()));
1✔
87
        });
1✔
88
        javalin.start();
1✔
89
        Suppressor.run(serverReadyLatch::await);
1✔
90
    }
1✔
91

92
    private void releaseAll() {
93
        for (String instanceName : new ArrayList<>(dalInstances.keySet()))
1✔
94
            release(instanceName);
1✔
95
    }
1✔
96

97
    private void release(String name) {
98
        DalInstance remove = dalInstances.remove(name);
1✔
99
        if (remove != null)
1✔
100
            remove.release();
1✔
101
    }
1✔
102

103
    public static void setDefaultMode(Mode mode) {
104
        Inspector.mode = mode;
1✔
105
    }
1✔
106

107
    private void exchange(String session, String body) {
108
        if (clientConnections.containsKey(session)) {
1✔
109
            clientMonitors.put(session, Arrays.stream(body.trim().split("\\n")).map(String::trim).filter(s -> !s.isEmpty()).collect(Collectors.toSet()));
1✔
110
        }
111
    }
1✔
112

113
    public static class DalInstance {
114
        private final Supplier<Object> input;
115
        private boolean running = true;
1✔
116
        private final DAL dal;
117
        private final String code;
118

119
        public DalInstance(Supplier<Object> input, DAL dal, String code) {
1✔
120
            this.input = input;
1✔
121
            this.dal = dal;
1✔
122
            this.code = code;
1✔
123
        }
1✔
124

125
        public String execute(String code) {
126
            Map<String, String> response = new HashMap<>();
1✔
127
            Object inputObject = input.get();
1✔
128
            RuntimeContextBuilder.DALRuntimeContext runtimeContext = dal.getRuntimeContextBuilder().build(inputObject);
1✔
129
            try {
130
                response.put("root", runtimeContext.wrap(inputObject).dumpAll());
1✔
131
                response.put("inspect", dal.compileSingle(code, runtimeContext).inspect());
1✔
132
                response.put("result", runtimeContext.wrap(dal.evaluate(inputObject, code)).dumpAll());
1✔
133
            } catch (InterpreterException e) {
1✔
134
                response.put("error", e.show(code) + "\n\n" + e.getMessage());
1✔
135
            }
1✔
136
            return ObjectWriter.serialize(response);
1✔
137
        }
138

139
        public void hold() {
140
//            TODO use logger
141
            System.err.println("Waiting for inspector response");
1✔
142
            //        TODO use sempahore to wait for the result
143
            while (running)
1✔
144
                Suppressor.run(() -> Thread.sleep(20));
1✔
145
//            TODO use logger
146
            System.err.println("inspector released");
1✔
147
        }
1✔
148

149
        public void release() {
150
            running = false;
1✔
151
        }
1✔
152
    }
153

154
    public void inspectInner(DAL dal, Object input, String code) {
155
        if (isRecursive())
1✔
156
            return;
1✔
157
//        lock inspect by name
158
//        check mode
159
        if (currentMode() == Mode.FORCED) {
1✔
160
            DalInstance dalInstance = new DalInstance(() -> input, dal, code);
1✔
161
            dalInstances.put(dal.getName(), dalInstance);
1✔
162

163
            List<WsContext> monitored = clientMonitors.entrySet().stream().filter(e -> e.getValue().contains(dal.getName()))
1✔
164
                    .map(o -> clientConnections.get(o.getKey()))
1✔
165
                    .collect(Collectors.toList());
1✔
166
            for (WsContext wsContext : monitored) {
1✔
167
                wsContext.send(ObjectWriter.serialize(new HashMap<String, String>() {{
1✔
168
                    put("request", dal.getName());
1✔
169
                }}));
1✔
170
            }
1✔
171

172
            dalInstance.hold();
1✔
173

174
        } else {
1✔
175
//        TODO refactor
176
            List<WsContext> monitored = clientMonitors.entrySet().stream().filter(e -> e.getValue().contains(dal.getName()))
1✔
177
                    .map(o -> clientConnections.get(o.getKey()))
1✔
178
                    .collect(Collectors.toList());
1✔
179
            if (!monitored.isEmpty()) {
1✔
180
                DalInstance dalInstance = new DalInstance(() -> input, dal, code);
1✔
181
                dalInstances.put(dal.getName(), dalInstance);
1✔
182
                for (WsContext wsContext : monitored) {
1✔
183
                    wsContext.send(ObjectWriter.serialize(new HashMap<String, String>() {{
1✔
184
                        put("request", dal.getName());
1✔
185
                    }}));
1✔
186
                }
1✔
187

188
                dalInstance.hold();
×
189
            }
190
        }
191
    }
1✔
192

193
    public static void inspect(DAL dal, Object input, String code) {
194
        if (currentMode() != Mode.DISABLED)
1✔
195
            inspector.inspectInner(dal, input, code);
1✔
196
    }
1✔
197

198
    private String request(String name) {
199
//       TODO reject other request
200
        return dalInstances.get(name).code;
1✔
201
    }
202

203
    private String execute(String name, String code) {
204
        return dalInstances.get(name).execute(code);
1✔
205
    }
206

207
    public static void register(DAL dal) {
208
        inspector.addInstance(dal);
1✔
209
    }
1✔
210

211
    private void addInstance(DAL dal) {
212
        instances.add(dal);
1✔
213
        for (WsContext ctx : clientConnections.values()) {
1✔
214
            sendInstances(ctx);
1✔
215
        }
1✔
216
    }
1✔
217

218
    private void sendInstances(WsContext ctx) {
219
        ctx.send(ObjectWriter.serialize(new HashMap<String, Object>() {{
1✔
220
            put("instances", instances.stream().map(DAL::getName).collect(Collectors.toSet()));
1✔
221
            put("session", ctx.getSessionId());
1✔
222
        }}));
1✔
223
    }
1✔
224

225
    private void stop() {
226
        javalin.close();
1✔
227
    }
1✔
228

229
    public static void launch() {
230
        if (inspector == null) {
1✔
231
            inspector = new Inspector();
1✔
232
        }
233
    }
1✔
234

235
    public static void shutdown() {
236
        if (inspector != null) {
1✔
237
            inspector.stop();
1✔
238
            inspector = null;
1✔
239
        }
240
    }
1✔
241

242
    public static void setDefaultInput(Supplier<Object> supplier) {
243
        defaultInput = supplier;
1✔
244
    }
1✔
245

246
    public static Mode currentMode() {
247
        return getFirstPresent(() -> ofNullable(mode),
1✔
248
                () -> ofNullable(System.getenv("DAL_INSPECTOR_MODE")).map(Mode::valueOf),
×
249
                () -> ofNullable(System.getProperty("dal.inspector.mode")).map(Mode::valueOf))
×
250
                .orElse(Mode.DISABLED);
1✔
251
    }
252

253
    public enum Mode {
1✔
254
        DISABLED, FORCED, AUTO
1✔
255
    }
256

257
    private boolean isRecursive() {
258
        for (StackTraceElement stack : Thread.currentThread().getStackTrace())
1✔
259
            if (DalInstance.class.getName().equals(stack.getClassName()))
1✔
260
                return true;
1✔
261
        return false;
1✔
262
    }
263

264
    public static void main(String[] args) {
265
        launch();
×
266
    }
×
267
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc