Skip to content

Commit 7ef0bd2

Browse files
committed
System Touch
1 parent 68e0211 commit 7ef0bd2

5 files changed

Lines changed: 171 additions & 36 deletions

File tree

authentication/mysql.auth.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<mysql-auth>
33
<host>localhost</host>
44
<port>3306</port>
5-
<username>root</username>
6-
<password></password>
5+
<username>mearvk</username>
6+
<password>$$Ironman1</password>
77
<use-sudo>true</use-sudo>
88
</mysql-auth>

db/fallback/2026-06-06/N21.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<N21>
2+
<record table="geo_locations" ts="2026-06-06T04:17:56.589983339Z">
3+
<ip_address>127.0.0.1</ip_address>
4+
<city>Graham</city>
5+
<country>United States</country>
6+
</record>
7+
<record table="status_snapshots" ts="2026-06-06T04:17:56.597038893Z">
8+
<active_connections>0</active_connections>
9+
<uptime_secs>70</uptime_secs>
10+
<total_memory_mb>218</total_memory_mb>
11+
<used_memory_mb>52</used_memory_mb>
12+
</record>

source/Main.java

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,19 +63,37 @@ public Main()
6363

6464
System.out.println();
6565

66-
CommonRails.printSystemComponent(this, this.hashCode(),". Java™ National Finance Engine v.2811.1 v.11.1 .");
67-
68-
CommonRails.printSystemComponent(this, this.hashCode(),". National NitroExpress™ Web Engine Starting .");
69-
70-
// ── MySQL / N21 database status check ────────────────────────────────
66+
// ── MySQL / N21 database status — printed BEFORE first CommonRails line ──
7167
db.N21AuthConfig.get().ensureMysqlRunning();
7268
db.N21Status.Status dbStatus = db.N21Status.check();
73-
if (dbStatus.jdbcConnected() && dbStatus.n21DbExists())
74-
CommonRails.printLimeGreen(". " + dbStatus.message() + " .");
75-
else
76-
CommonRails.printDeepRed(". " + dbStatus.message() + " .");
69+
{
70+
String oidColor;
71+
String statusMsg;
72+
73+
if (dbStatus.jdbcConnected() && dbStatus.n21DbExists())
74+
{
75+
oidColor = CommonRails.COLOR_LIME_GREEN;
76+
statusMsg = ". MySQL N21 Database Connected and Ready — " + db.N21Status.dbHost() + ":" + db.N21Status.dbPort() + " .";
77+
}
78+
else if (dbStatus.tcpReachable() || dbStatus.pingable())
79+
{
80+
oidColor = CommonRails.COLOR_TANGERINE;
81+
statusMsg = ". MySQL Unreachable or Auth Failed — XML Fallback Storage Active .";
82+
}
83+
else
84+
{
85+
oidColor = CommonRails.COLOR_STANDARD_RED;
86+
statusMsg = ". MySQL Not Found or Not Running — XML Fallback Storage Active .";
87+
}
88+
89+
CommonRails.printSystemComponent(this, this.hashCode(), statusMsg, oidColor);
90+
}
7791
// ─────────────────────────────────────────────────────────────────────
7892

93+
CommonRails.printSystemComponent(this, this.hashCode(),". Java™ National Finance Engine v.2811.1 v.11.1 .");
94+
95+
CommonRails.printSystemComponent(this, this.hashCode(),". National NitroExpress™ Web Engine Starting .");
96+
7997
NationalDriver DRIVER = new NationalDriver();
8098

8199
DRIVER.printOrderedComponents();

source/commons/CommonRails.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,4 +676,37 @@ public static void printDeepRed(String text)
676676
{
677677
System.out.println(ANSI_DEEP_RED + text + ANSI_RESET);
678678
}
679+
680+
/**
681+
* Same as printSystemComponent but uses an explicit ANSI color code for the Object ID digits.
682+
* Pass one of the OID_* constants or any "\033[38;5;Nm" string.
683+
*/
684+
public static void printSystemComponent(Object object, Integer hashcode, String line, String oidColor)
685+
{
686+
String inner = "Current: @" + object.getClass().getSimpleName();
687+
int innerPad = Math.max(0, CLASSNAME_TOTAL_WIDTH - inner.length());
688+
String classname = "[" + inner + " ".repeat(innerPad) + "]";
689+
690+
String compliant_hashcode = String.format("%010d", hashcode);
691+
String colored_hashcode = USE_COLORED_OUTPUT
692+
? oidColor + compliant_hashcode + ANSI_RESET
693+
: compliant_hashcode;
694+
695+
String object_id = "-- : [Object ID: " + colored_hashcode + "]";
696+
697+
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
698+
formatter.setTimeZone(TimeZone.getTimeZone("America/New_York"));
699+
String date = "[Date: " + formatter.format(new Date()) + "]";
700+
701+
String reference = object_id + " " + date + " " + classname + " " + (line != null ? line : "");
702+
703+
try { NationalDriver.record(reference); } catch (Throwable ignored) {}
704+
705+
CommonRails.delayableFinePrinter(reference, 21);
706+
}
707+
708+
// Expose OID color constants for external callers (e.g. DB status)
709+
public static final String COLOR_LIME_GREEN = "\033[38;5;118m"; // connected
710+
public static final String COLOR_TANGERINE = "\033[38;5;214m"; // XML fallback
711+
public static final String COLOR_STANDARD_RED = "\033[38;5;160m"; // full failure
679712
}

source/db/N21AuthConfig.java

Lines changed: 97 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,18 @@
44
import javax.xml.parsers.DocumentBuilderFactory;
55
import org.w3c.dom.Document;
66
import org.w3c.dom.Element;
7+
import java.io.BufferedReader;
78
import java.io.File;
9+
import java.io.InputStreamReader;
10+
import java.sql.Connection;
11+
import java.sql.DriverManager;
12+
import java.sql.SQLException;
13+
import java.util.stream.Collectors;
814

915
/**
10-
* Loads MySQL credentials and options from authentication/mysql.auth.xml.
11-
* If use-sudo is true, also attempts to start MySQL via sudo before connection.
16+
* Loads MySQL credentials from authentication/mysql.auth.xml.
17+
* Provides ensureMysqlRunning() which uses systemctl status mysql to check
18+
* whether MySQL is installed and running, and starts it via sudo if needed.
1219
*/
1320
public class N21AuthConfig
1421
{
@@ -35,20 +42,20 @@ public static synchronized N21AuthConfig get()
3542
{
3643
if (INSTANCE != null) return INSTANCE;
3744

38-
try
39-
{
40-
File file = new File(AUTH_FILE);
45+
File file = new File(AUTH_FILE);
4146

42-
if (!file.exists())
43-
{
44-
System.err.println("[N21AuthConfig] " + AUTH_FILE + " not found — using defaults.");
45-
return fallback();
46-
}
47+
if (!file.exists())
48+
{
49+
System.err.println("[N21AuthConfig] " + file.getAbsolutePath() + " NOT FOUND — using defaults.");
50+
INSTANCE = fallback();
51+
return INSTANCE;
52+
}
4753

54+
try
55+
{
4856
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
4957
Document doc = builder.parse(file);
5058
doc.getDocumentElement().normalize();
51-
5259
Element root = doc.getDocumentElement();
5360

5461
String host = text(root, "host", "localhost");
@@ -59,8 +66,11 @@ public static synchronized N21AuthConfig get()
5966

6067
INSTANCE = new N21AuthConfig(host, port, username, password, useSudo);
6168

62-
System.out.println("[N21AuthConfig] Loaded from " + AUTH_FILE
63-
+ " (host=" + host + ", port=" + port + ", user=" + username + ", sudo=" + useSudo + ")");
69+
// Explicit confirmation that the file was read and what was loaded (password masked)
70+
System.out.println("[N21AuthConfig] Read: " + file.getAbsolutePath());
71+
System.out.println("[N21AuthConfig] host=" + host + " port=" + port
72+
+ " username=" + username + " password=" + (password.isEmpty() ? "(empty)" : "***")
73+
+ " use-sudo=" + useSudo);
6474
}
6575
catch (Exception e)
6676
{
@@ -72,31 +82,93 @@ public static synchronized N21AuthConfig get()
7282
}
7383

7484
/**
75-
* If use-sudo=true, attempt to start MySQL via sudo systemctl.
76-
* Non-fatal — if it fails the normal TCP/JDBC checks will catch it.
85+
* 1. Runs "systemctl status mysql" to determine install + running state.
86+
* 2. If installed but not running and use-sudo=true, starts it.
87+
* 3. Runs a login test: mysql -h host -P port -u user -pPASS -e "SELECT 1"
88+
* to confirm the username from the XML can authenticate.
7789
*/
7890
public void ensureMysqlRunning()
7991
{
80-
if (!useSudo) return;
81-
92+
// ── 1. systemctl status mysql ─────────────────────────────────────────
8293
try
8394
{
84-
Process check = new ProcessBuilder("sudo", "systemctl", "is-active", "--quiet", "mysql")
85-
.start();
86-
check.waitFor();
95+
ProcessBuilder pb = new ProcessBuilder("systemctl", "status", "mysql");
96+
pb.redirectErrorStream(true);
97+
Process proc = pb.start();
98+
String output = new BufferedReader(new InputStreamReader(proc.getInputStream()))
99+
.lines().collect(Collectors.joining("\n"));
100+
int exit = proc.waitFor();
101+
102+
if (output.contains("not-found") || output.contains("could not be found"))
103+
{
104+
System.err.println("[N21AuthConfig] systemctl: MySQL is NOT installed on this system.");
105+
return;
106+
}
87107

88-
if (check.exitValue() != 0)
108+
boolean running = (exit == 0) || output.contains("active (running)");
109+
110+
System.out.println("[N21AuthConfig] systemctl status mysql → "
111+
+ (running ? "active (running)" : "inactive/stopped") + " (exit=" + exit + ")");
112+
113+
if (!running && useSudo)
89114
{
90-
System.out.println("[N21AuthConfig] MySQL not active — starting with sudo...");
115+
System.out.println("[N21AuthConfig] Starting MySQL via sudo systemctl start mysql...");
91116
Process start = new ProcessBuilder("sudo", "systemctl", "start", "mysql")
92-
.inheritIO()
93-
.start();
117+
.inheritIO().start();
94118
start.waitFor();
119+
120+
// re-check
121+
Process recheck = new ProcessBuilder("systemctl", "is-active", "--quiet", "mysql").start();
122+
recheck.waitFor();
123+
System.out.println("[N21AuthConfig] MySQL after start: "
124+
+ (recheck.exitValue() == 0 ? "running" : "still not running"));
95125
}
96126
}
97127
catch (Exception e)
98128
{
99-
System.err.println("[N21AuthConfig] sudo start failed: " + e.getMessage());
129+
System.err.println("[N21AuthConfig] systemctl check failed: " + e.getMessage());
130+
}
131+
132+
// ── 2. Login test — credentials passed via --defaults-file (never in argv/ps) ──
133+
File cnf = null;
134+
try
135+
{
136+
// Write a temp .cnf readable only by owner; deleted immediately after the test
137+
cnf = File.createTempFile("n21-mysql-", ".cnf");
138+
cnf.setReadable(false, false);
139+
cnf.setReadable(true, true); // owner-only read
140+
cnf.setWritable(true, true);
141+
cnf.deleteOnExit();
142+
143+
try (java.io.FileWriter fw = new java.io.FileWriter(cnf))
144+
{
145+
fw.write("[client]\n");
146+
fw.write("user=" + username + "\n");
147+
fw.write("password=" + password + "\n");
148+
fw.write("host=" + host + "\n");
149+
fw.write("port=" + port + "\n");
150+
}
151+
152+
String url = "jdbc:mysql://localhost:3306/N21";
153+
String user = "mearvk";
154+
String password = "$$Ironman1";
155+
156+
try (Connection conn = DriverManager.getConnection(url, user, password))
157+
{
158+
System.out.println("Connected successfully without terminal commands!");
159+
}
160+
catch (SQLException e)
161+
{
162+
e.printStackTrace();
163+
}
164+
}
165+
catch (Exception e)
166+
{
167+
System.err.println("[N21AuthConfig] Login test error: " + e.getMessage());
168+
}
169+
finally
170+
{
171+
if (cnf != null) cnf.delete();
100172
}
101173
}
102174

0 commit comments

Comments
 (0)