• 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/ConfigurationDialog.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 java.awt.*;
52
import java.io.IOException;
53
import java.nio.file.Files;
54
import java.nio.file.Path;
55
import java.nio.file.Paths;
56
import java.util.Map;
57
import java.util.Optional;
58
import java.util.Properties;
59
import java.util.function.Consumer;
60
import java.util.logging.Level;
61
import java.util.logging.Logger;
62
import java.util.stream.Stream;
63
import javax.swing.*;
64
import javax.xml.transform.TransformerException;
65

66
import org.exist.collections.CollectionCache;
67
import org.exist.storage.BrokerPool;
68
import org.exist.storage.DefaultCacheManager;
69
import org.exist.util.Configuration;
70
import org.exist.util.ConfigurationHelper;
71
import org.exist.util.DatabaseConfigurationException;
72
import org.exist.util.FileUtils;
73

74
import static org.exist.launcher.ConfigurationUtility.LAUNCHER_PROPERTY_MAX_MEM;
75
import static org.exist.launcher.ConfigurationUtility.LAUNCHER_PROPERTY_MIN_MEM;
76
import static org.exist.util.OSUtil.IS_MAC_OSX;
77

78
/**
79
 *
80
 * @author <a href="mailto:adam@evolvedbinary.com">Adam Retter</a>
81
 * @author wolf
82
 */
83
public class ConfigurationDialog extends JDialog {
84

85
    private final Consumer<Boolean> callback;
86
    private boolean changed = false;
×
87
    private boolean dataDirChanged = false;
×
88
    private boolean jettyConfigChanged = false;
×
89
    private boolean beforeStart = false;
×
90

91
    /**
92
     * Creates new form ConfigurationDialog
93
     *
94
     * @param callback a callback for after when the configuration is saved
95
     *     and the dialog is dismissed.
96
     */
97
    public ConfigurationDialog(Consumer<Boolean> callback) {
×
98
        setModal(true);
×
99
        setTitle("Elemental System Configuration");
×
100

101
        initComponents();
×
102

103
        this.callback = callback;
×
104
        
105
        final Properties launcherProperties = ConfigurationUtility.loadProperties();
×
106
        final int maxMemProp = Integer.parseInt(launcherProperties.getProperty(LAUNCHER_PROPERTY_MAX_MEM, "4096"));
×
107
        maxMemory.setValue(maxMemProp);
×
108
        final int minMemProp = Integer.parseInt(launcherProperties.getProperty(LAUNCHER_PROPERTY_MIN_MEM, "512"));
×
109
        minMemory.setValue(minMemProp);
×
110
        
111
        try {
112
            Configuration existConfig = new Configuration();
×
113
            final int cacheSizeProp = existConfig.getInteger(DefaultCacheManager.PROPERTY_CACHE_SIZE);
×
114
            cacheSize.setValue(cacheSizeProp);
×
115
            
116
            final int collectionCacheProp = existConfig.getInteger(CollectionCache.PROPERTY_CACHE_SIZE_BYTES);
×
117
            collectionCache.setValue(collectionCacheProp / 1024 / 1024); // show in MB
×
118

119
            final Path dir = (Path)existConfig.getProperty(BrokerPool.PROPERTY_DATA_DIR);
×
120
            dataDir.setText(dir.toAbsolutePath().toString());
×
121

122
            final Map<String, Integer> ports = ConfigurationUtility.getJettyPorts();
×
123
            if (ports.containsKey("jetty.port")) {
×
124
                httpPort.setValue(ports.get("jetty.port"));
×
125
            }
126
            if (ports.containsKey("jetty.http.port")) {
×
127
                httpPort.setValue(ports.get("jetty.http.port"));
×
128
            }
129
            if (ports.containsKey("ssl.port")) {
×
130
                sslPort.setValue(ports.get("ssl.port"));
×
131
            }
132
            if (ports.containsKey("jetty.ssl.port")) {
×
133
                sslPort.setValue(ports.get("jetty.ssl.port"));
×
134
            }
135
        } catch (DatabaseConfigurationException ex) {
×
136
            Logger.getLogger(ConfigurationDialog.class.getName()).log(Level.SEVERE, null, ex);
×
137
        }
138
        
139
        checkCacheBoundaries();
×
140

141
        changed = false;
×
142

143
        final Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
×
144
        this.setLocation(d.width - this.getWidth() - 40, 60);
×
145
        //setLocationRelativeTo(null);
146

147
        setAlwaysOnTop(true);
×
148
    }
×
149

150
    public void open(boolean firstStart) {
151
        if (firstStart) {
×
152
            beforeStart = true;
×
153
            // always check data dir on first start
154
            dataDirChanged = true;
×
155
            btnCancel.setVisible(false);
×
156
            lbStartupMsg.setVisible(true);
×
157
            lbStartupWarn.setVisible(true);
×
158

159
            if (IS_MAC_OSX) {
×
160
                Path dir = Paths.get(System.getProperty("user.home")).resolve("Library").resolve("Application Support").resolve("xyz.elemental");
×
161
                dataDir.setText(dir.toAbsolutePath().toString());
×
162
            }
163
        } else {
×
164
            lbStartupMsg.setVisible(false);
×
165
            lbStartupWarn.setVisible(false);
×
166
        }
167
        setVisible(true);
×
168
        requestFocus();
×
169
    }
×
170

171
    /**
172
     * This method is called from within the constructor to initialize the form.
173
     * WARNING: Do NOT modify this code. The content of this method is always
174
     * regenerated by the Form Editor.
175
     */
176
    @SuppressWarnings("unchecked")
177
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
178
    private void initComponents() {
179
        java.awt.GridBagConstraints gridBagConstraints;
180

181
        lbElementalLogo = new javax.swing.JLabel();
×
182
        jLabel1 = new javax.swing.JLabel();
×
183
        minMemory = new javax.swing.JSpinner();
×
184
        jLabel2 = new javax.swing.JLabel();
×
185
        maxMemory = new javax.swing.JSpinner();
×
186
        jLabel3 = new javax.swing.JLabel();
×
187
        jLabel4 = new javax.swing.JLabel();
×
188
        jLabel5 = new javax.swing.JLabel();
×
189
        cacheSize = new javax.swing.JSpinner();
×
190
        jLabel7 = new javax.swing.JLabel();
×
191
        collectionCache = new javax.swing.JSpinner();
×
192
        jLabel8 = new javax.swing.JLabel();
×
193
        lbCurrentUsage = new javax.swing.JLabel();
×
194
        lbStartupMsg = new javax.swing.JLabel();
×
195
        jLabel9 = new javax.swing.JLabel();
×
196
        jLabel10 = new javax.swing.JLabel();
×
197
        dataDir = new javax.swing.JTextField();
×
198
        jLabel11 = new javax.swing.JLabel();
×
199
        btnPanel = new javax.swing.JPanel();
×
200
        btnCancel = new javax.swing.JButton();
×
201
        btnSave = new javax.swing.JButton();
×
202
        btnSelectDir = new javax.swing.JButton();
×
203
        lbStartupWarn = new javax.swing.JLabel();
×
204
        jLabel11 = new javax.swing.JLabel();
×
205
        jLabel12 = new javax.swing.JLabel();
×
206
        jLabel13 = new javax.swing.JLabel();
×
207
        jLabel14 = new javax.swing.JLabel();
×
208
        jLabel15 = new javax.swing.JLabel();
×
209
        httpPort = new javax.swing.JSpinner();
×
210
        sslPort = new javax.swing.JSpinner();
×
211

212
        setTitle("Elemental Configuration");
×
213
        getContentPane().setLayout(new java.awt.GridBagLayout());
×
214

215
        lbElementalLogo.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/exist/client/icons/elemental-device.png"))); // NOI18N
×
216
        gridBagConstraints = new java.awt.GridBagConstraints();
×
217
        gridBagConstraints.gridx = 0;
×
218
        gridBagConstraints.gridy = 0;
×
219
        gridBagConstraints.gridheight = 6;
×
220
        gridBagConstraints.insets = new java.awt.Insets(0, 16, 0, 6);
×
221
        getContentPane().add(lbElementalLogo, gridBagConstraints);
×
222

223
        jLabel1.setText("Min Memory");
×
224
        gridBagConstraints = new java.awt.GridBagConstraints();
×
225
        gridBagConstraints.gridx = 1;
×
226
        gridBagConstraints.gridy = 4;
×
227
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
×
228
        gridBagConstraints.insets = new java.awt.Insets(0, 22, 0, 0);
×
229
        getContentPane().add(jLabel1, gridBagConstraints);
×
230

231
        minMemory.setModel(new javax.swing.SpinnerNumberModel(64, 64, 256, 64));
×
232
        minMemory.addChangeListener(this::minMemoryStateChanged);
×
233
        gridBagConstraints = new java.awt.GridBagConstraints();
×
234
        gridBagConstraints.gridx = 3;
×
235
        gridBagConstraints.gridy = 4;
×
236
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
×
237
        gridBagConstraints.ipadx = 1;
×
238
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
×
239
        getContentPane().add(minMemory, gridBagConstraints);
×
240

241
        jLabel2.setText("Max Memory");
×
242
        gridBagConstraints = new java.awt.GridBagConstraints();
×
243
        gridBagConstraints.gridx = 1;
×
244
        gridBagConstraints.gridy = 5;
×
245
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
×
246
        gridBagConstraints.insets = new java.awt.Insets(0, 22, 0, 0);
×
247
        getContentPane().add(jLabel2, gridBagConstraints);
×
248

249
        maxMemory.setModel(new javax.swing.SpinnerNumberModel(1024, 512, null, 64));
×
250
        maxMemory.addChangeListener(this::maxMemoryChanged);
×
251
        gridBagConstraints = new java.awt.GridBagConstraints();
×
252
        gridBagConstraints.gridx = 3;
×
253
        gridBagConstraints.gridy = 5;
×
254
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
×
255
        gridBagConstraints.ipadx = 1;
×
256
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
×
257
        getContentPane().add(maxMemory, gridBagConstraints);
×
258

259
        jLabel3.setFont(jLabel3.getFont().deriveFont(jLabel3.getFont().getStyle() | java.awt.Font.BOLD));
×
260
        jLabel3.setText("Java Memory");
×
261
        gridBagConstraints = new java.awt.GridBagConstraints();
×
262
        gridBagConstraints.gridx = 1;
×
263
        gridBagConstraints.gridy = 2;
×
264
        gridBagConstraints.gridwidth = 4;
×
265
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
×
266
        gridBagConstraints.insets = new java.awt.Insets(26, 22, 16, 0);
×
267
        getContentPane().add(jLabel3, gridBagConstraints);
×
268

269
        jLabel4.setFont(jLabel4.getFont().deriveFont(jLabel4.getFont().getStyle() | java.awt.Font.BOLD));
×
270
        jLabel4.setText("Caches");
×
271
        gridBagConstraints = new java.awt.GridBagConstraints();
×
272
        gridBagConstraints.gridx = 1;
×
273
        gridBagConstraints.gridy = 6;
×
274
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
×
275
        gridBagConstraints.insets = new java.awt.Insets(26, 22, 16, 0);
×
276
        getContentPane().add(jLabel4, gridBagConstraints);
×
277

278
        jLabel5.setText("General Cache");
×
279
        gridBagConstraints = new java.awt.GridBagConstraints();
×
280
        gridBagConstraints.gridx = 1;
×
281
        gridBagConstraints.gridy = 7;
×
282
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
×
283
        gridBagConstraints.insets = new java.awt.Insets(0, 22, 0, 0);
×
284
        getContentPane().add(jLabel5, gridBagConstraints);
×
285

286
        cacheSize.setModel(new javax.swing.SpinnerNumberModel(128, 48, 256, 16));
×
287
        cacheSize.addChangeListener(this::cacheSizeStateChanged);
×
288
        gridBagConstraints = new java.awt.GridBagConstraints();
×
289
        gridBagConstraints.gridx = 3;
×
290
        gridBagConstraints.gridy = 7;
×
291
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
×
292
        gridBagConstraints.ipadx = 1;
×
293
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
×
294
        getContentPane().add(cacheSize, gridBagConstraints);
×
295

296
        jLabel7.setText("Collection Cache");
×
297
        gridBagConstraints = new java.awt.GridBagConstraints();
×
298
        gridBagConstraints.gridx = 1;
×
299
        gridBagConstraints.gridy = 8;
×
300
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
×
301
        gridBagConstraints.insets = new java.awt.Insets(0, 22, 0, 0);
×
302
        getContentPane().add(jLabel7, gridBagConstraints);
×
303

304
        collectionCache.setModel(new javax.swing.SpinnerNumberModel(48, 48, 256, 16));
×
305
        collectionCache.addChangeListener(this::collectionCacheStateChanged);
×
306
        gridBagConstraints = new java.awt.GridBagConstraints();
×
307
        gridBagConstraints.gridx = 3;
×
308
        gridBagConstraints.gridy = 8;
×
309
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
×
310
        gridBagConstraints.ipadx = 1;
×
311
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
×
312
        getContentPane().add(collectionCache, gridBagConstraints);
×
313

314
        jLabel8.setText("<html>Memory settings only become effective after restart and only apply when Elemental is started via the system tray launcher.</html>");
×
315
        jLabel8.setPreferredSize(new java.awt.Dimension(280, 48));
×
316
        gridBagConstraints = new java.awt.GridBagConstraints();
×
317
        gridBagConstraints.gridx = 4;
×
318
        gridBagConstraints.gridy = 4;
×
319
        gridBagConstraints.gridheight = 2;
×
320
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
×
321
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
×
322
        gridBagConstraints.weightx = 1.0;
×
323
        gridBagConstraints.insets = new java.awt.Insets(0, 13, 0, 22);
×
324
        getContentPane().add(jLabel8, gridBagConstraints);
×
325

326
        lbCurrentUsage.setText("Memory usage (in MB):");
×
327
        gridBagConstraints = new java.awt.GridBagConstraints();
×
328
        gridBagConstraints.gridx = 1;
×
329
        gridBagConstraints.gridy = 3;
×
330
        gridBagConstraints.gridwidth = 4;
×
331
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
×
332
        gridBagConstraints.insets = new java.awt.Insets(12, 22, 12, 0);
×
333
        getContentPane().add(lbCurrentUsage, gridBagConstraints);
×
334

335
        lbStartupMsg.setFont(lbStartupMsg.getFont().deriveFont(lbStartupMsg.getFont().getStyle() & ~java.awt.Font.BOLD));
×
336
        lbStartupMsg.setText("<html>It seems you are starting Elemental for the first time. Please configure your memory settings below.</html>");
×
337
        lbStartupMsg.setMinimumSize(new java.awt.Dimension(60, 64));
×
338
        lbStartupMsg.setPreferredSize(new java.awt.Dimension(300, 32));
×
339
        gridBagConstraints = new java.awt.GridBagConstraints();
×
340
        gridBagConstraints.gridx = 1;
×
341
        gridBagConstraints.gridy = 0;
×
342
        gridBagConstraints.gridwidth = 4;
×
343
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
×
344
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
×
345
        gridBagConstraints.weightx = 1.0;
×
346
        gridBagConstraints.insets = new java.awt.Insets(27, 22, 0, 22);
×
347
        getContentPane().add(lbStartupMsg, gridBagConstraints);
×
348

349
        jLabel9.setText("<html>Changing the data directory will create an empty database in the new location (unless there's already data in it).</html>");
×
350
        jLabel9.setPreferredSize(new java.awt.Dimension(280, 48));
×
351
        gridBagConstraints = new java.awt.GridBagConstraints();
×
352
        gridBagConstraints.gridx = 4;
×
353
        gridBagConstraints.gridy = 10;
×
354
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
×
355
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
×
356
        gridBagConstraints.weightx = 1.0;
×
357
        gridBagConstraints.insets = new java.awt.Insets(0, 13, 0, 22);
×
358
        getContentPane().add(jLabel9, gridBagConstraints);
×
359

360
        jLabel10.setFont(jLabel10.getFont().deriveFont(jLabel10.getFont().getStyle() | java.awt.Font.BOLD));
×
361
        jLabel10.setText("Data Directory");
×
362
        gridBagConstraints = new java.awt.GridBagConstraints();
×
363
        gridBagConstraints.gridx = 1;
×
364
        gridBagConstraints.gridy = 9;
×
365
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
×
366
        gridBagConstraints.insets = new java.awt.Insets(26, 22, 16, 0);
×
367
        getContentPane().add(jLabel10, gridBagConstraints);
×
368

369
        dataDir.setMinimumSize(new java.awt.Dimension(180, 28));
×
370
        dataDir.setPreferredSize(new java.awt.Dimension(180, 28));
×
371
        dataDir.addActionListener(this::dataDirActionPerformed);
×
372
        gridBagConstraints = new java.awt.GridBagConstraints();
×
373
        gridBagConstraints.gridx = 1;
×
374
        gridBagConstraints.gridy = 10;
×
375
        gridBagConstraints.gridwidth = 2;
×
376
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
×
377
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
×
378
        gridBagConstraints.insets = new java.awt.Insets(0, 22, 0, 0);
×
379
        getContentPane().add(dataDir, gridBagConstraints);
×
380

381
        jLabel11.setText("<html>Total cache size should not exceed 1/3 of max memory unless you have more than 2GB available. These sizes are in megabytes.</html>");
×
382
        jLabel11.setPreferredSize(new java.awt.Dimension(280, 48));
×
383
        gridBagConstraints = new java.awt.GridBagConstraints();
×
384
        gridBagConstraints.gridx = 4;
×
385
        gridBagConstraints.gridy = 7;
×
386
        gridBagConstraints.gridheight = 2;
×
387
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
×
388
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
×
389
        gridBagConstraints.weightx = 1.0;
×
390
        gridBagConstraints.insets = new java.awt.Insets(0, 13, 0, 22);
×
391
        getContentPane().add(jLabel11, gridBagConstraints);
×
392

393
        btnPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.RIGHT));
×
394

395
        btnCancel.setText("Cancel");
×
396
        btnCancel.addActionListener(this::btnCancelActionPerformed);
×
397
        btnPanel.add(btnCancel);
×
398

399
        btnSave.setText("Save");
×
400
        btnSave.addActionListener(this::saveConfig);
×
401
        btnPanel.add(btnSave);
×
402

403
        gridBagConstraints = new java.awt.GridBagConstraints();
×
404
        gridBagConstraints.gridx = 1;
×
405
        gridBagConstraints.gridy = 14;
×
406
        gridBagConstraints.gridwidth = 4;
×
407
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
×
408
        gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHEAST;
×
409
        gridBagConstraints.weightx = 1.0;
×
410
        gridBagConstraints.insets = new java.awt.Insets(36, 13, 8, 0);
×
411
        getContentPane().add(btnPanel, gridBagConstraints);
×
412

413
        btnSelectDir.setText("Select");
×
414
        btnSelectDir.addActionListener(this::btnSelectDirActionPerformed);
×
415
        gridBagConstraints = new java.awt.GridBagConstraints();
×
416
        gridBagConstraints.gridx = 3;
×
417
        gridBagConstraints.gridy = 10;
×
418
        getContentPane().add(btnSelectDir, gridBagConstraints);
×
419

420
        lbStartupWarn.setFont(new java.awt.Font("Lucida Grande", 1, 13)); // NOI18N
×
421
        lbStartupWarn.setForeground(new java.awt.Color(255, 0, 0));
×
422
        lbStartupWarn.setText("<html>After startup, use dashboard or Java client to set a password for admin (empty by default).</html>");
×
423
        gridBagConstraints = new java.awt.GridBagConstraints();
×
424
        gridBagConstraints.gridx = 1;
×
425
        gridBagConstraints.gridy = 1;
×
426
        gridBagConstraints.gridwidth = 4;
×
427
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
×
428
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
×
429
        gridBagConstraints.insets = new java.awt.Insets(12, 22, 12, 22);
×
430
        getContentPane().add(lbStartupWarn, gridBagConstraints);
×
431

432
        jLabel12.setText("Jetty Ports");
×
433
        jLabel12.setFont(jLabel12.getFont().deriveFont(jLabel12.getFont().getStyle() | java.awt.Font.BOLD));
×
434
        gridBagConstraints = new java.awt.GridBagConstraints();
×
435
        gridBagConstraints.gridx = 1;
×
436
        gridBagConstraints.gridy = 11;
×
437
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
×
438
        gridBagConstraints.insets = new java.awt.Insets(26, 22, 16, 0);
×
439
        getContentPane().add(jLabel12, gridBagConstraints);
×
440

441
        jLabel13.setText("HTTP Port");
×
442
        gridBagConstraints = new java.awt.GridBagConstraints();
×
443
        gridBagConstraints.gridx = 1;
×
444
        gridBagConstraints.gridy = 12;
×
445
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
×
446
        gridBagConstraints.insets = new java.awt.Insets(0, 22, 0, 0);
×
447
        getContentPane().add(jLabel13, gridBagConstraints);
×
448

449
        httpPort.setModel(new javax.swing.SpinnerNumberModel(8080, 80, 100000, 1));
×
450
        httpPort.setEditor(new JSpinner.NumberEditor(httpPort, "#"));
×
451
        httpPort.addChangeListener(this::jettyConfigChanged);
×
452
        gridBagConstraints = new java.awt.GridBagConstraints();
×
453
        gridBagConstraints.gridx = 3;
×
454
        gridBagConstraints.gridy = 12;
×
455
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
×
456
        gridBagConstraints.ipadx = 1;
×
457
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
×
458
        getContentPane().add(httpPort, gridBagConstraints);
×
459

460
        jLabel14.setText("SSL Port");
×
461
        gridBagConstraints = new java.awt.GridBagConstraints();
×
462
        gridBagConstraints.gridx = 1;
×
463
        gridBagConstraints.gridy = 13;
×
464
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
×
465
        gridBagConstraints.insets = new java.awt.Insets(0, 22, 0, 0);
×
466
        getContentPane().add(jLabel14, gridBagConstraints);
×
467

468
        sslPort.setModel(new javax.swing.SpinnerNumberModel(8443, 80, 100000, 1));
×
469
        sslPort.setEditor(new JSpinner.NumberEditor(sslPort, "#"));
×
470
        sslPort.addChangeListener(this::jettyConfigChanged);
×
471
        gridBagConstraints = new java.awt.GridBagConstraints();
×
472
        gridBagConstraints.gridx = 3;
×
473
        gridBagConstraints.gridy = 13;
×
474
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
×
475
        gridBagConstraints.ipadx = 1;
×
476
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
×
477
        getContentPane().add(sslPort, gridBagConstraints);
×
478

479
        jLabel15.setText("<html>Set the ports used by the integrated web server. Please make sure " +
×
480
                "those ports are not used by other processes.</html>");
481
        jLabel15.setPreferredSize(new java.awt.Dimension(280, 48));
×
482
        gridBagConstraints = new java.awt.GridBagConstraints();
×
483
        gridBagConstraints.gridx = 4;
×
484
        gridBagConstraints.gridy = 12;
×
485
        gridBagConstraints.gridheight = 2;
×
486
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
×
487
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
×
488
        gridBagConstraints.weightx = 1.0;
×
489
        gridBagConstraints.insets = new java.awt.Insets(0, 13, 0, 22);
×
490
        getContentPane().add(jLabel15, gridBagConstraints);
×
491

492
        pack();
×
493
    }// </editor-fold>//GEN-END:initComponents
×
494

495
    private void btnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCancelActionPerformed
496
        setVisible(false);
×
497
    }//GEN-LAST:event_btnCancelActionPerformed
×
498

499
    private void maxMemoryChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_maxMemoryChanged
500
        checkCacheBoundaries();
×
501
        changed = true;
×
502
    }//GEN-LAST:event_maxMemoryChanged
×
503

504
    private boolean checkDataDir() {
505
        if (!dataDirChanged)
×
506
            return true;
×
507

508
        Path dir = Paths.get(dataDir.getText());
×
509
        if (Files.exists(dir)) {
×
510

511
            try (final Stream<Path> fileStream = Files.list(dir).filter(p -> FileUtils.fileName(p).endsWith(".dbx"))) {
×
512
                final boolean dbExists = fileStream.findFirst().isPresent();
×
513
                if (dbExists) {
×
514
                    final int r = JOptionPane.showConfirmDialog(this, "The specified data directory already contains data. " +
×
515
                            "Do you want to use this? Data will not be removed.", "Confirm Data Directory", JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
×
516
                    if (r == JOptionPane.OK_OPTION) {
×
517
                        return true;
×
518
                    }
519
                    return false;
×
520
                }
521
            } catch (final IOException e) {
×
522
                JOptionPane.showMessageDialog(this, "Failed to enumerate data files from directory: " + dir.toAbsolutePath().toString(),
×
523
                    "Failed to enumerate data files", JOptionPane.ERROR_MESSAGE);
×
524
                return false;
×
525
            }
526
        } else {
527
            final int r = JOptionPane.showConfirmDialog(this, "The specified data directory does not exist. Do you want to create it?",
×
528
                "Create data directory?", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
×
529
            if (r == JOptionPane.YES_OPTION) {
×
530
                try {
531
                    Files.createDirectories(dir);
×
532
                } catch (IOException e) {
×
533
                    JOptionPane.showMessageDialog(this, "Failed to create data directory: " + dir.toAbsolutePath().toString(),
×
534
                            "Failed to create directory", JOptionPane.ERROR_MESSAGE);
×
535
                    return false;
×
536
                }
537
                return true;
×
538
            }
539
            return false;
×
540
        }
541
        if (!Files.isWritable(dir)) {
×
542
            JOptionPane.showMessageDialog(this, "The specified data directory is not writable. " +
×
543
                    "Please choose a different one.", "Data Directory Error", JOptionPane.ERROR_MESSAGE);
×
544
            return false;
×
545
        }
546
        return true;
×
547
    }
548

549
    private void saveConfig(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveConfig
550
        if (!beforeStart && !changed && !dataDirChanged && !jettyConfigChanged) {
×
551
            setVisible(false);
×
552
            return;
×
553
        }
554
        if (!checkDataDir())
×
555
            return;
×
556
        try {
557
            final Properties properties = new Properties();
×
558
            properties.setProperty("memory.max", maxMemory.getValue().toString());
×
559
            properties.setProperty("memory.min", minMemory.getValue().toString());
×
560

561
            // save the launcher properties
562
            ConfigurationUtility.saveProperties(properties);
×
563

564
            properties.clear();
×
565

566
            // update conf.xml
567
            properties.setProperty("cacheSize", cacheSize.getValue().toString());
×
568
            properties.setProperty("collectionCache", collectionCache.getValue().toString());
×
569
            properties.setProperty("dataDir", dataDir.getText());
×
570
            ConfigurationUtility.saveConfiguration("conf.xml", "conf.xsl", properties);
×
571

572
            properties.clear();
×
573

574
            if (jettyConfigChanged) {
×
575
                // update Jetty confs
576
                properties.setProperty("port", httpPort.getValue().toString());
×
577
                properties.setProperty("port.ssl", sslPort.getValue().toString());
×
578
                ConfigurationUtility.saveConfiguration("jetty/jetty-ssl.xml", "jetty.xsl", properties);
×
579
                ConfigurationUtility.saveConfiguration("jetty/jetty-http.xml", "jetty.xsl", properties);
×
580
            }
581

582
            if (beforeStart) {
×
583
                beforeStart = false;
×
584
                btnCancel.setVisible(true);
×
585
                setVisible(false);
×
586
                callback.accept(true);
×
587
            } else if (changed || dataDirChanged || jettyConfigChanged) {
×
588
                int r = JOptionPane.showConfirmDialog(this, "Database needs to be restarted to apply the " +
×
589
                            "new settings.", "Confirm restart", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
×
590
                if (r == JOptionPane.YES_OPTION) {
×
591
                    changed = false;
×
592
                    dataDirChanged = false;
×
593
                    setVisible(false);
×
594
                    callback.accept(true);
×
595
                }
596
            }
597
        } catch (final IOException e) {
×
598
            e.printStackTrace();
×
599
            JOptionPane.showMessageDialog(this, "Failed to save Java settings: " + e.getMessage(),
×
600
                    "Save Error", JOptionPane.ERROR_MESSAGE);
×
601
        } catch (TransformerException e) {
×
602
            e.printStackTrace();
×
603
            JOptionPane.showMessageDialog(this, "Failed to save configuration: " + e.getMessage() +
×
604
                    " at " + e.getLocationAsString(),
×
605
                    "Save Error", JOptionPane.ERROR_MESSAGE);
×
606
        }
607
    }//GEN-LAST:event_saveConfig
×
608

609
    private void cacheSizeStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_cacheSizeStateChanged
610
        changed = true;
×
611
        checkCacheBoundaries();
×
612
    }//GEN-LAST:event_cacheSizeStateChanged
×
613

614
    private void collectionCacheStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_collectionCacheStateChanged
615
        changed = true;
×
616
    }//GEN-LAST:event_collectionCacheStateChanged
×
617

618
    private void minMemoryStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_minMemoryStateChanged
619
        changed = true;
×
620
    }//GEN-LAST:event_minMemoryStateChanged
×
621

622
    private void dataDirActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dataDirActionPerformed
623
        dataDirChanged = true;
×
624
    }//GEN-LAST:event_dataDirActionPerformed
×
625

626
    private void jettyConfigChanged(javax.swing.event.ChangeEvent evt) {
627
        jettyConfigChanged = true;
×
628
    }
×
629

630
    private void btnSelectDirActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSelectDirActionPerformed
631
        final Optional<Path> currentDir = Optional.ofNullable(dataDir.getText())
×
632
                .map(d -> Optional.of(Paths.get(d)))
×
633
                .filter(md -> md.map(Files::exists).orElse(false))
×
634
                .orElse(ConfigurationHelper.getExistHome());
×
635

636
        final JFileChooser chooser = new JFileChooser();
×
637
        chooser.setMultiSelectionEnabled(false);
×
638
        chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
×
639

640
        currentDir.map(Path::toFile).ifPresent(chooser::setCurrentDirectory);
×
641

642
        if(chooser.showDialog(this, "Choose Data Directory") == JFileChooser.APPROVE_OPTION) {
×
643
            dataDir.setText(chooser.getSelectedFile().getAbsolutePath());
×
644
            dataDirChanged = true;
×
645
        }
646
    }//GEN-LAST:event_btnSelectDirActionPerformed
×
647

648
    private void checkCacheBoundaries() {
649
        showCurrentMem();
×
650
        final int max = (Integer)maxMemory.getValue();
×
651
        final SpinnerNumberModel cacheModel = (SpinnerNumberModel) cacheSize.getModel();
×
652
        final SpinnerNumberModel collectionCacheModel = (SpinnerNumberModel) collectionCache.getModel();
×
653
        int maxCache;
654
        if (max <= 2048) {
×
655
            maxCache = (max / 3);
×
656
        } else {
×
657
            maxCache = (max / 2);
×
658
        }
659
        cacheModel.setMaximum(maxCache - 48);
×
660
        if (((Integer)cacheModel.getMaximum()).compareTo((Integer)cacheModel.getValue()) < 0) {
×
661
            cacheModel.setValue(cacheModel.getMaximum());
×
662
        }
663
        collectionCacheModel.setMaximum(maxCache - (Integer)cacheModel.getValue());
×
664
        if (((Integer)collectionCacheModel.getMaximum()).compareTo((Integer)collectionCacheModel.getValue()) < 0) {
×
665
            collectionCacheModel.setValue(collectionCacheModel.getMaximum());
×
666
        }
667
    }
×
668

669
    private void showCurrentMem() {
670
        lbCurrentUsage.setText("Memory usage: " + (Runtime.getRuntime().freeMemory() / 1024 / 1024) +
×
671
            " free/" + (Runtime.getRuntime().maxMemory() / 1024 / 1024) + " max mb");
×
672
    }
×
673

674
    // Variables declaration - do not modify//GEN-BEGIN:variables
675
    private javax.swing.JButton btnCancel;
676
    private javax.swing.JPanel btnPanel;
677
    private javax.swing.JButton btnSave;
678
    private javax.swing.JButton btnSelectDir;
679
    private javax.swing.JSpinner cacheSize;
680
    private javax.swing.JSpinner collectionCache;
681
    private javax.swing.JTextField dataDir;
682
    private javax.swing.JLabel jLabel1;
683
    private javax.swing.JLabel jLabel2;
684
    private javax.swing.JLabel jLabel3;
685
    private javax.swing.JLabel jLabel4;
686
    private javax.swing.JLabel jLabel5;
687
    private javax.swing.JLabel jLabel7;
688
    private javax.swing.JLabel jLabel8;
689
    private javax.swing.JLabel jLabel9;
690
    private javax.swing.JLabel jLabel10;
691
    private javax.swing.JLabel jLabel11;
692
    private javax.swing.JLabel jLabel12;
693
    private javax.swing.JLabel jLabel13;
694
    private javax.swing.JLabel jLabel14;
695
    private javax.swing.JLabel jLabel15;
696
    private javax.swing.JLabel lbCurrentUsage;
697
    private javax.swing.JLabel lbElementalLogo;
698
    private javax.swing.JLabel lbStartupMsg;
699
    private javax.swing.JLabel lbStartupWarn;
700
    private javax.swing.JSpinner maxMemory;
701
    private javax.swing.JSpinner minMemory;
702
    private javax.swing.JSpinner httpPort;
703
    private javax.swing.JSpinner sslPort;
704
    // End of variables declaration//GEN-END:variables
705

706
}
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