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

evolvedbinary / elemental / 982

29 Apr 2025 08:34PM UTC coverage: 56.409% (+0.007%) from 56.402%
982

push

circleci

adamretter
[feature] Improve README.md badges

28451 of 55847 branches covered (50.94%)

Branch coverage included in aggregate %.

77468 of 131924 relevant lines covered (58.72%)

0.59 hits per line

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

0.0
/exist-core/src/main/java/org/exist/launcher/LauncherWrapper.java
1
/*
2
 * Elemental
3
 * Copyright (C) 2024, Evolved Binary Ltd
4
 *
5
 * admin@evolvedbinary.com
6
 * https://www.evolvedbinary.com | https://www.elemental.xyz
7
 *
8
 * Use of this software is governed by the Business Source License 1.1
9
 * included in the LICENSE file and at www.mariadb.com/bsl11.
10
 *
11
 * Change Date: 2028-04-27
12
 *
13
 * On the date above, in accordance with the Business Source License, use
14
 * of this software will be governed by the Apache License, Version 2.0.
15
 *
16
 * Additional Use Grant: Production use of the Licensed Work for a permitted
17
 * purpose. A Permitted Purpose is any purpose other than a Competing Use.
18
 * A Competing Use means making the Software available to others in a commercial
19
 * product or service that: substitutes for the Software; substitutes for any
20
 * other product or service we offer using the Software that exists as of the
21
 * date we make the Software available; or offers the same or substantially
22
 * similar functionality as the Software.
23
 *
24
 * NOTE: Parts of this file contain code from 'The eXist-db Authors'.
25
 *       The original license header is included below.
26
 *
27
 * =====================================================================
28
 *
29
 * eXist-db Open Source Native XML Database
30
 * Copyright (C) 2001 The eXist-db Authors
31
 *
32
 * info@exist-db.org
33
 * http://www.exist-db.org
34
 *
35
 * This library is free software; you can redistribute it and/or
36
 * modify it under the terms of the GNU Lesser General Public
37
 * License as published by the Free Software Foundation; either
38
 * version 2.1 of the License, or (at your option) any later version.
39
 *
40
 * This library is distributed in the hope that it will be useful,
41
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
42
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
43
 * Lesser General Public License for more details.
44
 *
45
 * You should have received a copy of the GNU Lesser General Public
46
 * License along with this library; if not, write to the Free Software
47
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
48
 */
49
package org.exist.launcher;
50

51
import org.exist.start.CompatibleJavaVersionCheck;
52
import org.exist.start.StartException;
53
import org.exist.util.ConfigurationHelper;
54
import org.exist.util.OSUtil;
55
import org.exist.util.SystemExitCodes;
56
import se.softhouse.jargo.Argument;
57
import se.softhouse.jargo.ArgumentException;
58
import se.softhouse.jargo.CommandLineParser;
59

60
import javax.swing.*;
61
import java.io.File;
62
import java.io.IOException;
63
import java.nio.file.Files;
64
import java.nio.file.Path;
65
import java.nio.file.Paths;
66
import java.util.*;
67

68
import static org.exist.launcher.ConfigurationUtility.*;
69
import static se.softhouse.jargo.Arguments.helpArgument;
70

71
/**
72
 * A wrapper to start a Java process using start.jar with correct VM settings.
73
 * Spawns a new Java VM using Ant. Mainly used when launching
74
 * Elemental by double-clicking on start.jar.
75
 *
76
 * @author <a href="mailto:adam@evolvedbinary.com">Adam Retter</a>
77
 * @author Tobi Krebs
78
 * @author Wolfgang Meier
79
 */
80
public class LauncherWrapper {
81

82
    private static final String LAUNCHER = org.exist.launcher.Launcher.class.getName();
×
83

84
    /* general arguments */
85
    private static final Argument<?> helpArg = helpArgument("-h", "--help");
×
86

87
    public final static void main(final String[] args) {
88
        try {
89
            CompatibleJavaVersionCheck.checkForCompatibleJavaVersion();
×
90

91
            // parse command-line options
92
            CommandLineParser
×
93
                    .withArguments(helpArg)
×
94
                    .programName("launcher" + (OSUtil.IS_WINDOWS ? ".bat" : ".sh"))
×
95
                    .parse(args);
×
96

97
        } catch (final StartException e) {
×
98
            if (e.getMessage() != null && !e.getMessage().isEmpty()) {
×
99
                System.err.println(e.getMessage());
×
100
            }
101
            System.exit(e.getErrorCode());
×
102
        } catch (final ArgumentException e) {
×
103
            consoleOut(e.getMessageAndUsage().toString());
×
104
            System.exit(SystemExitCodes.INVALID_ARGUMENT_EXIT_CODE);
×
105
        }
106

107
        final LauncherWrapper wrapper = new LauncherWrapper(LAUNCHER);
×
108
        if (ConfigurationUtility.isFirstStart()) {
×
109
            System.out.println("First launch: opening configuration dialog");
×
110
            ConfigurationDialog configDialog = new ConfigurationDialog(restart -> {
×
111
                wrapper.launch();
×
112
                // make sure the process dies when the dialog is closed
113
                System.exit(0);
×
114
            });
×
115
            configDialog.open(true);
×
116
            configDialog.requestFocus();
×
117
        } else {
×
118
            wrapper.launch();
×
119
        }
120
    }
×
121

122
    protected String command;
123

124
    public LauncherWrapper(String command) {
×
125
        this.command = command;
×
126
    }
×
127

128
    public void launch() {
129
        final String debugLauncher = System.getProperty("exist.debug.launcher", "false");
×
130
        final Properties launcherProperties = ConfigurationUtility.loadProperties();
×
131

132
        final List<String> args = new ArrayList<>();
×
133
        args.add(getJavaCmd());
×
134
        getJavaOpts(args, launcherProperties);
×
135

136
        if (Boolean.parseBoolean(debugLauncher) && !"client".equals(command)) {
×
137
            args.add("-Xdebug");
×
138
            args.add("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5006");
×
139

140
            System.out.println("Debug mode for Launcher on JDWP port 5006. Will await connection...");
×
141
        }
142

143
        // recreate the classpath
144
        args.add("-cp");
×
145
        args.add(getClassPath());
×
146

147
        // call exist main with our new command
148
        args.add("org.exist.start.Main");
×
149
        args.add(command);
×
150

151
        try {
152
            run(args);
×
153
        } catch (final IOException e) {
×
154
            JOptionPane.showMessageDialog(null, e.getMessage(), "Error Running Process", JOptionPane.ERROR_MESSAGE);
×
155
        }
156
    }
×
157

158
    private String getClassPath() {
159
        // if we are booted using appassembler-booter, then we should use `app.class.path`
160
        return System.getProperty("app.class.path", System.getProperty("java.class.path"));
×
161
    }
162

163
    private void run(final List<String> args) throws IOException {
164
        final StringBuilder buf = new StringBuilder("Executing: [");
×
165
        for (int i = 0; i < args.size(); i++) {
×
166
            buf.append('"');
×
167
            buf.append(args.get(i));
×
168
            buf.append('"');
×
169
            if (i != args.size() - 1) {
×
170
                buf.append(", ");
×
171
            }
172
        }
173
        buf.append(']');
×
174
        System.out.println(buf.toString());
×
175

176
        final ProcessBuilder pb = new ProcessBuilder(args);
×
177
        final Optional<Path> home = ConfigurationHelper.getExistHome();
×
178
        pb.directory(home.orElse(Paths.get(".")).toFile());
×
179
        pb.redirectErrorStream(true);
×
180
        pb.inheritIO();
×
181

182
        pb.start();
×
183
    }
×
184

185

186
    protected String getJavaCmd() {
187
        final File javaHome = new File(System.getProperty("java.home"));
×
188
        if (OSUtil.IS_WINDOWS) {
×
189
            Path javaBin = Paths.get(javaHome.getAbsolutePath(), "bin", "javaw.exe");
×
190
            if (Files.isExecutable(javaBin)) {
×
191
                return '"' + javaBin.toString() + '"';
×
192
            }
193
            javaBin = Paths.get(javaHome.getAbsolutePath(), "bin", "java.exe");
×
194
            if (Files.isExecutable(javaBin)) {
×
195
                return '"' + javaBin.toString() + '"';
×
196
            }
197
        } else {
198
            Path javaBin = Paths.get(javaHome.getAbsolutePath(), "bin", "java");
×
199
            if (Files.isExecutable(javaBin)) {
×
200
                return javaBin.toString();
×
201
            }
202
        }
203
        return "java";
×
204
    }
205

206
    protected void getJavaOpts(final List<String> args, final Properties launcherProperties) {
207
        getLauncherOpts(args, launcherProperties);
×
208

209
        boolean foundExistHomeSysProp = false;
×
210
        final Properties sysProps = System.getProperties();
×
211
        for (final Map.Entry<Object, Object> entry : sysProps.entrySet()) {
×
212
            final String key = entry.getKey().toString();
×
213
            if (key.startsWith("exist.") || key.startsWith("log4j.") || key.startsWith("jetty.") || key.startsWith("app.")) {
×
214
                args.add("-D" + key + "=" + entry.getValue().toString());
×
215
                if (key.equals("exist.home")) {
×
216
                    foundExistHomeSysProp = true;
×
217
                }
218
            }
219
        }
220

221
        if (!foundExistHomeSysProp) {
×
222
            args.add("-Dexist.home=\".\"");
×
223
        }
224

225
        if (command.equals(LAUNCHER) && OSUtil.IS_MAC_OSX) {
×
226
            args.add("-Dapple.awt.UIElement=true");
×
227
        }
228
    }
×
229

230
    protected void getLauncherOpts(final List<String> args, final Properties launcherProperties) {
231
        for (final String key : launcherProperties.stringPropertyNames()) {
×
232
            if (key.startsWith("memory.")) {
×
233
                if (LAUNCHER_PROPERTY_MAX_MEM.equals(key)) {
×
234
                    args.add("-Xmx" + launcherProperties.getProperty(key) + 'm');
×
235
                } else if (LAUNCHER_PROPERTY_MIN_MEM.equals(key)) {
×
236
                    args.add("-Xms" + launcherProperties.getProperty(key) + 'm');
×
237
                }
238
            } else if (LAUNCHER_PROPERTY_VMOPTIONS.equals(key)) {
×
239
                args.add(launcherProperties.getProperty(key));
×
240
            } else if (key.startsWith(LAUNCHER_PROPERTY_VMOPTIONS + '.')) {
×
241
                final String os = key.substring((LAUNCHER_PROPERTY_VMOPTIONS + '.').length()).toLowerCase();
×
242
                if (OSUtil.OS_NAME.toLowerCase().contains(os)) {
×
243
                    final String value = launcherProperties.getProperty(key);
×
244
                    Arrays.stream(value.split("\\s+")).forEach(args::add);
×
245
                }
246
            }
247
        }
248
    }
×
249

250
    private static void consoleOut(final String msg) {
251
        System.out.println(msg); //NOSONAR this has to go to the console
×
252
    }
×
253
}
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