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

oracle / opengrok / #3731

30 Nov 2023 04:39PM CUT coverage: 66.148% (-8.7%) from 74.811%
#3731

push

vladak
update Tomcat to 10.1.16

fixes #4492

38758 of 58593 relevant lines covered (66.15%)

0.66 hits per line

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

0.0
/opengrok-indexer/src/main/java/org/opengrok/indexer/analysis/document/MandocRunner.java
1
/*
2
 * CDDL HEADER START
3
 *
4
 * The contents of this file are subject to the terms of the
5
 * Common Development and Distribution License (the "License").
6
 * You may not use this file except in compliance with the License.
7
 *
8
 * See LICENSE.txt included in this distribution for the specific
9
 * language governing permissions and limitations under the License.
10
 *
11
 * When distributing Covered Code, include this CDDL HEADER in each
12
 * file and include the License file at LICENSE.txt.
13
 * If applicable, add the following below this CDDL HEADER, with the
14
 * fields enclosed by brackets "[]" replaced with your own identifying
15
 * information: Portions Copyright [yyyy] [name of copyright owner]
16
 *
17
 * CDDL HEADER END
18
 */
19

20
/*
21
 * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
22
 * Copyright (c) 2017, 2018, Chris Fraire <cfraire@me.com>.
23
 */
24
package org.opengrok.indexer.analysis.document;
25

26
import java.io.BufferedReader;
27
import java.io.IOException;
28
import java.io.InputStream;
29
import java.io.InputStreamReader;
30
import java.io.OutputStreamWriter;
31
import java.nio.charset.StandardCharsets;
32
import java.util.ArrayList;
33
import java.util.List;
34
import java.util.concurrent.TimeUnit;
35
import java.util.logging.Level;
36
import java.util.logging.Logger;
37
import org.opengrok.indexer.configuration.RuntimeEnvironment;
38
import org.opengrok.indexer.logger.LoggerFactory;
39
import org.opengrok.indexer.util.IOUtils;
40

41
/**
42
 * Represents a wrapper to run mandoc binary to format manual page content.
43
 */
44
public class MandocRunner {
×
45
    private static final Logger LOGGER = LoggerFactory.getLogger(
×
46
        MandocRunner.class);
47

48
    private Process mandoc;
49
    private OutputStreamWriter mandocIn;
50
    private BufferedReader mandocOut;
51
    private Thread errThread;
52
    private String osOverride = "GENERIC SYSTEM";
×
53

54
    /**
55
     * Gets the value used for mandoc's setting to "Override the default
56
     * operating system name". Default is {@code "GENERIC SYSTEM"}.
57
     * @return a defined value or {@code null}
58
     */
59
    public String getOSOverride() {
60
        return osOverride;
×
61
    }
62

63
    /**
64
     * Sets the value used for mandoc's setting to "Override the default
65
     * operating system name".
66
     * @param value a defined value or {@code null} to disable the override
67
     */
68
    public void setOSOverride( String value ) {
69
        osOverride = value;
×
70
    }
×
71

72
    /**
73
     * Starts a run of the mandoc binary to receive input from {@link #write}.
74
     * @throws IOException thrown if a read or write to the mandoc process
75
     * fails.
76
     * @throws MandocException if no mandoc binary is defined
77
     */
78
    public void start() throws IOException, MandocException {
79

80
        destroy();
×
81

82
        RuntimeEnvironment env = RuntimeEnvironment.getInstance();
×
83
        String binary = env.getMandoc();
×
84
        if (binary == null) {
×
85
            throw new MandocException("no mandoc binary is defined");
×
86
        }
87

88
        List<String> command = new ArrayList<>();
×
89

90
        command.add(binary);
×
91
        command.add("-c");  // do not use `more`
×
92
        command.add("-Kutf-8");  // explicitly set the output encoding
×
93
        command.add("-Thtml");  // Produce HTML5, CSS1, and MathML output
×
94
        command.add("-Ofragment");  // HTML fragment only
×
95

96
        // Override the default operating system name
97
        String oo = osOverride;
×
98
        if (oo != null) {
×
99
            command.add("-I");
×
100
            command.add("os=" + oo);
×
101
        }
102

103
        if (LOGGER.isLoggable(Level.FINER)) {
×
104
            StringBuilder sb = new StringBuilder();
×
105
            command.forEach(s -> sb.append(s).append(" "));
×
106
            String cmd = sb.toString();
×
107
            LOGGER.log(Level.FINER, "Executing mandoc command [{0}]", cmd);
×
108
        }
109

110
        ProcessBuilder processBuilder = new ProcessBuilder(command);
×
111

112
        Process starting = processBuilder.start();
×
113
        OutputStreamWriter inn = new OutputStreamWriter(
×
114
            starting.getOutputStream(), StandardCharsets.UTF_8);
×
115
        BufferedReader rdr = new BufferedReader(new InputStreamReader(
×
116
            starting.getInputStream(), StandardCharsets.UTF_8));
×
117
        InputStream errorStream = starting.getErrorStream();
×
118
        mandocIn = inn;
×
119
        mandocOut = rdr;
×
120
        mandoc = starting;
×
121

122
        errThread = new Thread(() -> {
×
123
            // implicitly capture `errorStream' for the InputStreamReader
124
            try (BufferedReader error = new BufferedReader(new InputStreamReader(errorStream, StandardCharsets.UTF_8))) {
×
125
                String s;
126
                while ((s = error.readLine()) != null) {
×
127
                    LOGGER.log(Level.WARNING, "Error from mandoc: {0}", s);
×
128
                }
129
            } catch (IOException ex) {
×
130
                // ignore
131
            }
×
132
        });
×
133
        errThread.setDaemon(true);
×
134
        errThread.start();
×
135
    }
×
136

137
    /**
138
     * Finishes a run of mandoc for its output.
139
     * @return the stdout output of the run.
140
     * @throws IOException thrown if closing the mandoc process fails.
141
     * @throws MandocException thrown if mandoc exits non-zero.
142
     */
143
    public String finish() throws IOException, MandocException {
144
        if (mandoc == null) {
×
145
            return "";
×
146
        }
147

148
        StringBuilder output = new StringBuilder();
×
149

150
        int rc;
151
        try {
152
            String line;
153
            mandocIn.close();
×
154
            while ((line = mandocOut.readLine()) != null) {
×
155
                output.append(line);
×
156
                output.append('\n');
×
157
            }
158
            mandoc.waitFor(10, TimeUnit.SECONDS);
×
159
            rc = mandoc.exitValue();
×
160
        } catch (InterruptedException e) {
×
161
            return "";
×
162
        } finally {
163
            destroy();
×
164
        }
165

166
        if (rc != 0) {
×
167
            throw new MandocException("exit code " + rc);
×
168
        }
169
        return output.toString();
×
170
    }
171

172
    /**
173
     * Writes a character to the input of the run of mandoc.
174
     * @param s the string to write.
175
     * @throws IllegalStateException thrown if the runner was not successfully
176
     * {@link #start}ed.
177
     * @throws IOException thrown if a write to the mandoc process fails.
178
     */
179
    public void write(String s) throws IOException {
180
        if (mandocIn == null) {
×
181
            throw new IllegalStateException("start() must succeed first");
×
182
        }
183

184
        mandocIn.write(s);
×
185
    }
×
186

187
    /**
188
     * Kills the mandoc process if it is running.
189
     */
190
    public void destroy() {
191
        // terminate straightaway any existing run
192
        if (errThread != null) {
×
193
            errThread.interrupt();
×
194
            errThread = null;
×
195
        }
196
        if (mandoc != null) {
×
197
            Process destroying = mandoc;
×
198
            mandoc = null;
×
199

200
            if (mandocIn != null) {
×
201
                IOUtils.close(mandocIn);
×
202
                mandocIn = null;
×
203
            }
204
            if (mandocOut != null) {
×
205
                IOUtils.close(mandocOut);
×
206
                mandocOut = null;
×
207
            }
208

209
            destroying.destroyForcibly();
×
210
        }
211
    }
×
212
}
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