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

nats-io / java-nats-server-runner / #7

pending completion
#7

push

github-actions

web-flow
Bump GH Actions versions (Go; node12 deprecation) (#26)

Bump three GitHub Actions versions to move away from the deprecated
node.js 12 bases and so reduce warning noise in Actions output:

    actions/setup-java  v2 -> v3
    actions/setup-go    v2 -> v3
    actions/checkout    v2 -> v3

Bump Golang version 1.19.1 to 1.19.9; also, quote the string for defensiveness
against version number parsing and YAML string vs version numbers.  While we're
unlikely to switch to patch-level-unspecified in future, protect against
mistakes by quoting, as we're doing for all repos.

378 of 454 relevant lines covered (83.26%)

0.83 hits per line

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

74.29
/src/main/java/nats/io/NatsOutputLogger.java
1
// Copyright 2020-2023 The NATS Authors
2
// Licensed under the Apache License, Version 2.0 (the "License");
3
// you may not use this file except in compliance with the License.
4
// You may obtain a copy of the License at:
5
//
6
// http://www.apache.org/licenses/LICENSE-2.0
7
//
8
// Unless required by applicable law or agreed to in writing, software
9
// distributed under the License is distributed on an "AS IS" BASIS,
10
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
// See the License for the specific language governing permissions and
12
// limitations under the License.
13

14
package nats.io;
15

16
import java.io.BufferedReader;
17
import java.io.IOException;
18
import java.io.InputStreamReader;
19
import java.io.UncheckedIOException;
20
import java.lang.invoke.MethodHandles;
21
import java.lang.invoke.MethodType;
22
import java.lang.reflect.Field;
23
import java.nio.charset.StandardCharsets;
24
import java.util.logging.Logger;
25

26
/**
27
 * Read standard output of process and write lines to given {@link Logger} as INFO;
28
 * depends on {@link ProcessBuilder#redirectErrorStream(boolean)} being set to {@code true} (since only stdout is
29
 * read).
30
 *
31
 * <p>
32
 * The use of the input stream is threadsafe since it's used only in a single thread&mdash;the one launched by this
33
 * code.
34
 */
35
final class NatsOutputLogger implements Runnable {
36
    private final Output output;
37
    private final BufferedReader reader;
38

39
    private NatsOutputLogger(Output output, Process process) {
1✔
40
        this.output = output;
1✔
41
        this.reader = new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8));
1✔
42
    }
1✔
43

44
    private void logLine(String line) {
45
        output.info(() -> line);
1✔
46
    }
1✔
47

48
    @Override
49
    public void run() {
50
        try {
51
            try {
52
                reader.lines().forEach(this::logLine);
×
53
            } catch (final UncheckedIOException e) {
1✔
54
                output.warning(() -> "while reading output " + e);
1✔
55
            }
×
56
        } finally {
57
            try {
58
                reader.close();
1✔
59
            } catch (final IOException e) {
×
60
                output.warning(() -> "caught i/o exception closing reader" + e);
×
61
            }
1✔
62
        }
63
    }
1✔
64

65
    static void logOutput(final Output output, final Process process, final String processName) {
66
        final String threadName = (isBlank(processName) ? "unknown" : processName) + ":" + processId(process);
1✔
67
        final Thread t = new Thread(new NatsOutputLogger(output, process));
1✔
68
        t.setName(threadName);
1✔
69
        t.setDaemon(true);
1✔
70
        t.start();
1✔
71
    }
1✔
72

73
    private static String processId(Process process) {
74
        try { // java 9+
75
            return String.format("pid(%s)", MethodHandles.lookup().findVirtual(Process.class, "pid", MethodType.methodType(long.class)).invoke(process));
×
76
        } catch (Throwable ignored) {} // NOPMD since MethodHandles.invoke throws Throwable
1✔
77

78
        try { // openjdk / oraclejdk 8
79
            final Field pid = process.getClass().getDeclaredField("pid");
1✔
80
            pid.setAccessible(true);
1✔
81
            return String.format("pid(%s)", pid.getInt(process));
1✔
82
        } catch (Exception ignored) {} // NOPMD
×
83

84
        return String.format("id(%s)", process.hashCode());
×
85
    }
86

87
    private static boolean isBlank(final CharSequence cs) {
88
        final int strLen = cs.length();
1✔
89
        if (strLen == 0) {
1✔
90
            return true;
×
91
        }
92
        for (int i = 0; i < strLen; i++) {
1✔
93
            if (!Character.isWhitespace(cs.charAt(i))) {
1✔
94
                return false;
1✔
95
            }
96
        }
97
        return true;
×
98
    }
99
}
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

© 2025 Coveralls, Inc