Fix MfApi ClassNotFound by passing Java classpath via ArgumentList.
Use ct-ZADBService and explicit MfClientLibPath so SMC restart finds client JARs. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,12 +1,12 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"Id": 1,
|
"Id": 1,
|
||||||
"Name": "DE-Test Container",
|
"Name": "DE-Test / ct-ZADBService",
|
||||||
"Environment": "TEST",
|
"Environment": "TEST",
|
||||||
"IsActive": true,
|
"IsActive": true,
|
||||||
"TargetDirectory": "DeploySandbox/target-esb",
|
"TargetDirectory": "DeploySandbox/target-esb",
|
||||||
"CertificateFileName": "esb-cert.cer",
|
"CertificateFileName": "esb-cert.cer",
|
||||||
"ContainerName": "DE-Test",
|
"ContainerName": "ct-ZADBService",
|
||||||
"RestartType": "SonicContainer",
|
"RestartType": "SonicContainer",
|
||||||
"RestartCommand": "",
|
"RestartCommand": "",
|
||||||
"RestartArguments": "",
|
"RestartArguments": "",
|
||||||
|
|||||||
@@ -345,16 +345,21 @@ public sealed class SonicManagementClient : IDisposable
|
|||||||
$"Domain={_connection.DomainName}; ConnectionUrl={_connection.ConnectionUrl}\n{output}");
|
$"Domain={_connection.DomainName}; ConnectionUrl={_connection.ConnectionUrl}\n{output}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string libHint = string.IsNullOrWhiteSpace(_connection.MfClientLibPath)
|
||||||
|
? _connection.SonicHome
|
||||||
|
: _connection.MfClientLibPath;
|
||||||
|
|
||||||
return (false, "Neustart fehlgeschlagen (MfApi)",
|
return (false, "Neustart fehlgeschlagen (MfApi)",
|
||||||
"Laut Doku (Management Application API / wie SMC-Restart):\n" +
|
"Laut Doku (Management Application API / wie SMC-Restart):\n" +
|
||||||
"JMSConnectorClient + MFProxyFactory.createAgentProxy + IAgentProxy.restart\n\n" +
|
"JMSConnectorClient + MFProxyFactory.createAgentProxy + IAgentProxy.restart\n\n" +
|
||||||
$"Container '{containerName}', Domain '{_connection.DomainName}', URL {_connection.ConnectionUrl}\n" +
|
$"Container '{containerName}', Domain '{_connection.DomainName}', URL {_connection.ConnectionUrl}\n" +
|
||||||
$"Fehler: {error}\nAusgabe: {output}\n\n" +
|
$"Fehler: {error}\nAusgabe: {output}\n\n" +
|
||||||
"Benötigt (SMC-Installation):\n" +
|
"Benötigt (SMC-Installation):\n" +
|
||||||
$"- SonicHome={_connection.SonicHome} mit lib\\*.jar (mgmt_client / mfcontext / sonic_Client)\n" +
|
$"- MfClientLibPath/SonicHome={libHint} (mgmt_client.jar, mfcontext.jar, sonic_Client.jar)\n" +
|
||||||
"- Java (JavaHome/JavaPath oder JRE unter SonicHome)\n" +
|
$"- JavaPath={_connection.JavaPath}\n" +
|
||||||
"- Dieselben ConnectionUrl/User/Pass wie beim SMC-Login\n" +
|
"- Dieselben ConnectionUrl/User/Pass wie beim SMC-Login\n" +
|
||||||
"Hinweis: stopcontainer.bat wird nicht verwendet (in SMC-only Versionen oft nicht vorhanden).");
|
"SMC-ObjectName Beispiel: proalpha-test.ct-ZADBService:ID=AGENT → ContainerName=ct-ZADBService\n" +
|
||||||
|
"Hinweis: stopcontainer.bat wird nicht verwendet (SMC-only).");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<bool> IsTcpReachableAsync(string connectionUrl, CancellationToken cancellationToken)
|
private static async Task<bool> IsTcpReachableAsync(string connectionUrl, CancellationToken cancellationToken)
|
||||||
|
|||||||
@@ -105,27 +105,11 @@ public sealed class SonicMfApiExecutor
|
|||||||
return (false, null, prepareError);
|
return (false, null, prepareError);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<string> args =
|
// ArgumentList statt manueller Quotes: sonst landet \"...\" im Classpath
|
||||||
[
|
// und Java findet JMSConnectorAddress trotz vorhandener JARs nicht.
|
||||||
"-cp", Quote(classpath!),
|
|
||||||
"SonicMfContainerTool",
|
|
||||||
command,
|
|
||||||
"--domain", _connection.DomainName,
|
|
||||||
"--url", _connection.ConnectionUrl,
|
|
||||||
"--user", _connection.Username,
|
|
||||||
"--timeout", Math.Clamp(_connection.TimeoutSeconds, 5, 600).ToString()
|
|
||||||
];
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(container))
|
|
||||||
{
|
|
||||||
args.Add("--container");
|
|
||||||
args.Add(container);
|
|
||||||
}
|
|
||||||
|
|
||||||
ProcessStartInfo psi = new()
|
ProcessStartInfo psi = new()
|
||||||
{
|
{
|
||||||
FileName = javaExe!,
|
FileName = javaExe!,
|
||||||
Arguments = string.Join(" ", args.Select(EscapeArg)),
|
|
||||||
UseShellExecute = false,
|
UseShellExecute = false,
|
||||||
RedirectStandardOutput = true,
|
RedirectStandardOutput = true,
|
||||||
RedirectStandardError = true,
|
RedirectStandardError = true,
|
||||||
@@ -135,6 +119,25 @@ public sealed class SonicMfApiExecutor
|
|||||||
WorkingDirectory = classDir!
|
WorkingDirectory = classDir!
|
||||||
};
|
};
|
||||||
|
|
||||||
|
psi.ArgumentList.Add("-cp");
|
||||||
|
psi.ArgumentList.Add(classpath!);
|
||||||
|
psi.ArgumentList.Add("SonicMfContainerTool");
|
||||||
|
psi.ArgumentList.Add(command);
|
||||||
|
psi.ArgumentList.Add("--domain");
|
||||||
|
psi.ArgumentList.Add(_connection.DomainName);
|
||||||
|
psi.ArgumentList.Add("--url");
|
||||||
|
psi.ArgumentList.Add(_connection.ConnectionUrl);
|
||||||
|
psi.ArgumentList.Add("--user");
|
||||||
|
psi.ArgumentList.Add(_connection.Username);
|
||||||
|
psi.ArgumentList.Add("--timeout");
|
||||||
|
psi.ArgumentList.Add(Math.Clamp(_connection.TimeoutSeconds, 5, 600).ToString());
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(container))
|
||||||
|
{
|
||||||
|
psi.ArgumentList.Add("--container");
|
||||||
|
psi.ArgumentList.Add(container);
|
||||||
|
}
|
||||||
|
|
||||||
psi.Environment["ESB_SONIC_PASSWORD"] = _connection.Password ?? string.Empty;
|
psi.Environment["ESB_SONIC_PASSWORD"] = _connection.Password ?? string.Empty;
|
||||||
|
|
||||||
using Process process = new() { StartInfo = psi };
|
using Process process = new() { StartInfo = psi };
|
||||||
@@ -172,6 +175,17 @@ public sealed class SonicMfApiExecutor
|
|||||||
|
|
||||||
string err = ExtractError(combined)
|
string err = ExtractError(combined)
|
||||||
?? $"SonicMfContainerTool ExitCode={process.ExitCode}";
|
?? $"SonicMfContainerTool ExitCode={process.ExitCode}";
|
||||||
|
|
||||||
|
if (err.Contains("ClassNotFoundException", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| combined.Contains("JMSConnectorAddress", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
err +=
|
||||||
|
"\n\nClasspath unvollständig: com.sonicsw.mf.jmx.client.JMSConnectorAddress fehlt.\n" +
|
||||||
|
"Bitte in appsettings MfClientLibPath auf den Ordner mit mgmt_client.jar / mfcontext.jar / sonic_Client.jar setzen\n" +
|
||||||
|
$"(aktuell SonicHome='{_connection.SonicHome}').\n" +
|
||||||
|
"Hinweis: Container-Kurzname laut SMC ist 'ct-ZADBService' (nicht der Verbindungs-Alias DE-Test).";
|
||||||
|
}
|
||||||
|
|
||||||
return (false, combined.Length > 0 ? combined : null, err);
|
return (false, combined.Length > 0 ? combined : null, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,8 +240,8 @@ public sealed class SonicMfApiExecutor
|
|||||||
"Sonic-Client-JARs bleiben unter SonicHome\\lib.");
|
"Sonic-Client-JARs bleiben unter SonicHome\\lib.");
|
||||||
}
|
}
|
||||||
|
|
||||||
(string? libDir, string? libError) = ResolveLibDirectoryDetailed();
|
(string? libClasspath, string? libError) = ResolveSonicClasspathDetailed();
|
||||||
if (libDir is null)
|
if (libClasspath is null)
|
||||||
{
|
{
|
||||||
return (false, null, null, null, libError);
|
return (false, null, null, null, libError);
|
||||||
}
|
}
|
||||||
@@ -236,7 +250,7 @@ public sealed class SonicMfApiExecutor
|
|||||||
if (TryResolvePrebuiltTool(runtimeMajor, out string? prebuiltDir, out string? prebuiltEntry, out string? prebuiltError)
|
if (TryResolvePrebuiltTool(runtimeMajor, out string? prebuiltDir, out string? prebuiltEntry, out string? prebuiltError)
|
||||||
&& prebuiltDir is not null && prebuiltEntry is not null)
|
&& prebuiltDir is not null && prebuiltEntry is not null)
|
||||||
{
|
{
|
||||||
string classpath = BuildClasspath(libDir, prebuiltEntry);
|
string classpath = libClasspath + Path.PathSeparator + prebuiltEntry;
|
||||||
return (true, javaExe, prebuiltDir, classpath, null);
|
return (true, javaExe, prebuiltDir, classpath, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,8 +272,8 @@ public sealed class SonicMfApiExecutor
|
|||||||
|
|
||||||
File.Copy(sourcePath, javaTarget, overwrite: true);
|
File.Copy(sourcePath, javaTarget, overwrite: true);
|
||||||
|
|
||||||
string compileClasspath = BuildClasspath(libDir, null);
|
string compileClasspath = libClasspath;
|
||||||
string runtimeClasspath = BuildClasspath(libDir, workDir);
|
string runtimeClasspath = libClasspath + Path.PathSeparator + workDir;
|
||||||
|
|
||||||
bool classOk = File.Exists(classFile)
|
bool classOk = File.Exists(classFile)
|
||||||
&& ReadClassFileMajorVersion(classFile) is int existingMajor
|
&& ReadClassFileMajorVersion(classFile) is int existingMajor
|
||||||
@@ -285,8 +299,6 @@ public sealed class SonicMfApiExecutor
|
|||||||
ProcessStartInfo compilePsi = new()
|
ProcessStartInfo compilePsi = new()
|
||||||
{
|
{
|
||||||
FileName = javac,
|
FileName = javac,
|
||||||
Arguments =
|
|
||||||
$"{releaseArgs} -encoding UTF-8 -cp {Quote(compileClasspath)} -d {Quote(workDir)} {Quote(javaTarget)}",
|
|
||||||
UseShellExecute = false,
|
UseShellExecute = false,
|
||||||
RedirectStandardOutput = true,
|
RedirectStandardOutput = true,
|
||||||
RedirectStandardError = true,
|
RedirectStandardError = true,
|
||||||
@@ -295,6 +307,27 @@ public sealed class SonicMfApiExecutor
|
|||||||
StandardErrorEncoding = Encoding.UTF8
|
StandardErrorEncoding = Encoding.UTF8
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (releaseArgs.StartsWith("--release", StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
compilePsi.ArgumentList.Add("--release");
|
||||||
|
compilePsi.ArgumentList.Add("8");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
compilePsi.ArgumentList.Add("-source");
|
||||||
|
compilePsi.ArgumentList.Add("1.8");
|
||||||
|
compilePsi.ArgumentList.Add("-target");
|
||||||
|
compilePsi.ArgumentList.Add("1.8");
|
||||||
|
}
|
||||||
|
|
||||||
|
compilePsi.ArgumentList.Add("-encoding");
|
||||||
|
compilePsi.ArgumentList.Add("UTF-8");
|
||||||
|
compilePsi.ArgumentList.Add("-cp");
|
||||||
|
compilePsi.ArgumentList.Add(compileClasspath);
|
||||||
|
compilePsi.ArgumentList.Add("-d");
|
||||||
|
compilePsi.ArgumentList.Add(workDir);
|
||||||
|
compilePsi.ArgumentList.Add(javaTarget);
|
||||||
|
|
||||||
using Process compile = new() { StartInfo = compilePsi };
|
using Process compile = new() { StartInfo = compilePsi };
|
||||||
if (!compile.Start())
|
if (!compile.Start())
|
||||||
{
|
{
|
||||||
@@ -312,7 +345,7 @@ public sealed class SonicMfApiExecutor
|
|||||||
"Kompilieren von SonicMfContainerTool für Java 8 fehlgeschlagen.\n" +
|
"Kompilieren von SonicMfContainerTool für Java 8 fehlgeschlagen.\n" +
|
||||||
Truncate((cErr + "\n" + cOut).Trim()) +
|
Truncate((cErr + "\n" + cOut).Trim()) +
|
||||||
$"\nErzeugt major={builtMajor?.ToString() ?? "?"}, Runtime erlaubt <={runtimeMajor}.\n" +
|
$"\nErzeugt major={builtMajor?.ToString() ?? "?"}, Runtime erlaubt <={runtimeMajor}.\n" +
|
||||||
$"Classpath-Lib: {libDir}");
|
$"Classpath: {Truncate(compileClasspath, 240)}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -543,13 +576,17 @@ public sealed class SonicMfApiExecutor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private (string? Dir, string? Error) ResolveLibDirectoryDetailed()
|
/// <summary>
|
||||||
|
/// Baut einen Classpath mit echten Sonic-Management-Client-JARs
|
||||||
|
/// (inkl. com.sonicsw.mf.jmx.client.JMSConnectorAddress).
|
||||||
|
/// </summary>
|
||||||
|
private (string? Classpath, string? Error) ResolveSonicClasspathDetailed()
|
||||||
{
|
{
|
||||||
List<(string Path, string Label)> candidates = [];
|
List<(string Path, string Label)> searchRoots = [];
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(_connection.MfClientLibPath))
|
if (!string.IsNullOrWhiteSpace(_connection.MfClientLibPath))
|
||||||
{
|
{
|
||||||
candidates.Add((_connection.MfClientLibPath.Trim(), "MfClientLibPath"));
|
searchRoots.Add((_connection.MfClientLibPath.Trim().Trim('"'), "MfClientLibPath"));
|
||||||
}
|
}
|
||||||
|
|
||||||
string? mqHome = Environment.GetEnvironmentVariable("MQ_HOME");
|
string? mqHome = Environment.GetEnvironmentVariable("MQ_HOME");
|
||||||
@@ -559,92 +596,262 @@ public sealed class SonicMfApiExecutor
|
|||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(mqHome))
|
if (!string.IsNullOrWhiteSpace(mqHome))
|
||||||
{
|
{
|
||||||
candidates.Add((Path.Combine(mqHome.Trim().Trim('"'), "lib"), "MQ_HOME\\lib"));
|
searchRoots.Add((mqHome.Trim().Trim('"'), "MQ_HOME"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(esbHome))
|
if (!string.IsNullOrWhiteSpace(esbHome))
|
||||||
{
|
{
|
||||||
string esb = esbHome.Trim().Trim('"');
|
searchRoots.Add((esbHome.Trim().Trim('"'), "ESB_HOME/SONIC_HOME"));
|
||||||
candidates.Add((Path.Combine(esb, "lib"), "ESB_HOME\\lib"));
|
|
||||||
candidates.Add((Path.Combine(esb, "MQ", "lib"), "ESB_HOME\\MQ\\lib"));
|
|
||||||
candidates.Add((Path.Combine(esb, "mq", "lib"), "ESB_HOME\\mq\\lib"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(_connection.SonicHome))
|
if (!string.IsNullOrWhiteSpace(_connection.SonicHome))
|
||||||
{
|
{
|
||||||
string sonicHome = _connection.SonicHome.Trim();
|
string sonicHome = _connection.SonicHome.Trim().Trim('"');
|
||||||
candidates.Add((Path.Combine(sonicHome, "lib"), "SonicHome\\lib"));
|
searchRoots.Add((sonicHome, "SonicHome"));
|
||||||
candidates.Add((sonicHome, "SonicHome"));
|
|
||||||
|
|
||||||
// ESB-Home zeigt oft auf Broker/ESB; Client-JARs liegen unter MQ*/lib oder sibling MQ.
|
|
||||||
foreach (string nested in EnumerateLikelyLibRoots(sonicHome))
|
|
||||||
{
|
|
||||||
candidates.Add((nested, "SonicHome-nested\\lib"));
|
|
||||||
}
|
|
||||||
|
|
||||||
string? parent = Directory.GetParent(sonicHome)?.FullName;
|
string? parent = Directory.GetParent(sonicHome)?.FullName;
|
||||||
if (!string.IsNullOrWhiteSpace(parent))
|
if (!string.IsNullOrWhiteSpace(parent))
|
||||||
{
|
{
|
||||||
candidates.Add((Path.Combine(parent, "lib"), "SonicHome-Parent\\lib"));
|
searchRoots.Add((parent, "SonicHome-Parent"));
|
||||||
foreach (string nested in EnumerateLikelyLibRoots(parent))
|
|
||||||
{
|
|
||||||
candidates.Add((nested, "SonicHome-Parent-nested\\lib"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<string> checkedPaths = [];
|
List<string> checkedPaths = [];
|
||||||
HashSet<string> seen = new(StringComparer.OrdinalIgnoreCase);
|
HashSet<string> seenDirs = new(StringComparer.OrdinalIgnoreCase);
|
||||||
foreach ((string path, string label) in candidates)
|
List<string> markerHits = [];
|
||||||
|
|
||||||
|
foreach ((string root, string label) in searchRoots)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(path) || !seen.Add(path))
|
if (string.IsNullOrWhiteSpace(root) || !Directory.Exists(root))
|
||||||
|
{
|
||||||
|
checkedPaths.Add($"{label}='{root}' (fehlt)");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkedPaths.Add($"{label}='{root}'");
|
||||||
|
|
||||||
|
// 1) Bekannte Lib-Ordner
|
||||||
|
List<string> libCandidates = [root, Path.Combine(root, "lib"), .. EnumerateLikelyLibRoots(root)];
|
||||||
|
|
||||||
|
// 2) Rekursiv nach Marker-JARs (SMC-only oft unter MQ*/lib oder Client/lib)
|
||||||
|
foreach (string jar in EnumerateMarkerJars(root, maxDepth: 5, maxFiles: 400))
|
||||||
|
{
|
||||||
|
string? dir = Path.GetDirectoryName(jar);
|
||||||
|
if (!string.IsNullOrWhiteSpace(dir))
|
||||||
|
{
|
||||||
|
libCandidates.Add(dir);
|
||||||
|
markerHits.Add(jar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string libDir in libCandidates)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(libDir) || !seenDirs.Add(libDir) || !Directory.Exists(libDir))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
checkedPaths.Add($"{label}='{path}'");
|
if (!DirectoryHasRequiredSonicClientJars(libDir, out string? detail))
|
||||||
if (!Directory.Exists(path))
|
|
||||||
{
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(detail))
|
||||||
|
{
|
||||||
|
checkedPaths.Add($" skip '{libDir}': {detail}");
|
||||||
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DirectoryHasSonicClientJars(path))
|
string? classpath = BuildClasspathFromLibDirs(CollectRelatedLibDirs(libDir, root));
|
||||||
|
if (!string.IsNullOrWhiteSpace(classpath))
|
||||||
{
|
{
|
||||||
return (path, null);
|
return (classpath, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string sonicHomeVal = _connection.SonicHome ?? string.Empty;
|
string sonicHomeVal = _connection.SonicHome ?? string.Empty;
|
||||||
bool sonicHomeExists = !string.IsNullOrWhiteSpace(sonicHomeVal) && Directory.Exists(sonicHomeVal);
|
string markerHint = markerHits.Count == 0
|
||||||
string libPath = string.IsNullOrWhiteSpace(sonicHomeVal)
|
? "Keine Marker-JARs (mgmt_client/mfcontext/sonic_Client) gefunden."
|
||||||
? "(SonicHome leer)"
|
: "Marker-Treffer (unvollständig):\n - " + string.Join("\n - ", markerHits.Distinct(StringComparer.OrdinalIgnoreCase).Take(12));
|
||||||
: Path.Combine(sonicHomeVal, "lib");
|
|
||||||
|
|
||||||
if (sonicHomeExists && Directory.Exists(libPath)
|
|
||||||
&& !Directory.EnumerateFiles(libPath, "*.jar", SearchOption.TopDirectoryOnly).Any())
|
|
||||||
{
|
|
||||||
return (null,
|
|
||||||
$"Sonic-Client-JARs fehlen unter '{libPath}' (Ordner existiert, aber keine *.jar).\n" +
|
|
||||||
$"Verwendetes SonicHome: '{sonicHomeVal}'\n" +
|
|
||||||
"MfApi braucht u.a. mgmt_client.jar / mfcontext.jar / sonic_Client.jar.\n" +
|
|
||||||
"Falls SonicHome auf ESB zeigt: auf MQ-Home setzen oder MfClientLibPath auf den MQ\\lib-Ordner.\n" +
|
|
||||||
$"Geprüft: {string.Join("; ", checkedPaths)}");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sonicHomeExists && !Directory.Exists(libPath))
|
|
||||||
{
|
|
||||||
return (null,
|
|
||||||
$"SonicHome='{sonicHomeVal}' gefunden, aber Lib-Ordner fehlt: '{libPath}'.\n" +
|
|
||||||
"Sonic-Client-Installation prüfen oder MfClientLibPath setzen " +
|
|
||||||
"(erwartet *.jar, u.a. mgmt_client.jar).\n" +
|
|
||||||
$"Geprüft: {string.Join("; ", checkedPaths)}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return (null,
|
return (null,
|
||||||
"Sonic-Client-JARs nicht gefunden. SonicHome\\lib, MQ_HOME\\lib, ESB_HOME\\lib oder MfClientLibPath setzen.\n" +
|
"Sonic-Client-JARs für MfApi fehlen (Class JMSConnectorAddress).\n" +
|
||||||
$"Verwendetes SonicHome: '{(string.IsNullOrWhiteSpace(sonicHomeVal) ? "(leer)" : sonicHomeVal)}'\n" +
|
$"Verwendetes SonicHome: '{(string.IsNullOrWhiteSpace(sonicHomeVal) ? "(leer)" : sonicHomeVal)}'\n" +
|
||||||
$"Geprüft:\n - {string.Join("\n - ", checkedPaths)}\n" +
|
"Benötigt u.a.: mgmt_client.jar, mfcontext.jar, sonic_Client.jar (Ordner mit *.jar).\n" +
|
||||||
"Benötigt u.a. mgmt_client.jar / mfcontext.jar / sonic_Client.jar.");
|
"Lösung: MfClientLibPath auf den Ordner setzen, in dem diese JARs liegen\n" +
|
||||||
|
" (oft ...\\MQ10.0\\lib oder SMC-Client\\lib – nicht nur das JRE).\n" +
|
||||||
|
markerHint + "\n" +
|
||||||
|
"Geprüft:\n - " + string.Join("\n - ", checkedPaths.Take(40)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<string> EnumerateMarkerJars(string root, int maxDepth, int maxFiles)
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(root))
|
||||||
|
{
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
|
string[] markers =
|
||||||
|
[
|
||||||
|
"mgmt_client", "mfcontext", "sonic_Client", "sonic_client",
|
||||||
|
"mf_client", "mf-client", "mgmt-client", "sonic_Crypto", "sonic_XA"
|
||||||
|
];
|
||||||
|
|
||||||
|
Queue<(string Dir, int Depth)> queue = new();
|
||||||
|
queue.Enqueue((root, 0));
|
||||||
|
int yielded = 0;
|
||||||
|
HashSet<string> seen = new(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
while (queue.Count > 0 && yielded < maxFiles)
|
||||||
|
{
|
||||||
|
(string dir, int depth) = queue.Dequeue();
|
||||||
|
if (!seen.Add(dir))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerable<string> files;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
files = Directory.EnumerateFiles(dir, "*.jar", SearchOption.TopDirectoryOnly);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string file in files)
|
||||||
|
{
|
||||||
|
string name = Path.GetFileNameWithoutExtension(file);
|
||||||
|
if (markers.Any(m => name.Contains(m, StringComparison.OrdinalIgnoreCase)))
|
||||||
|
{
|
||||||
|
yielded++;
|
||||||
|
yield return file;
|
||||||
|
if (yielded >= maxFiles)
|
||||||
|
{
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (depth >= maxDepth)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerable<string> children;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
children = Directory.EnumerateDirectories(dir);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string child in children)
|
||||||
|
{
|
||||||
|
string leaf = Path.GetFileName(child);
|
||||||
|
// Skip große / irrelevante Bäume
|
||||||
|
if (leaf.Equals("docs", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| leaf.Equals("documentation", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| leaf.Equals("samples", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| leaf.Equals("log", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| leaf.Equals("logs", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| leaf.Equals("tmp", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| leaf.Equals("temp", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| leaf.StartsWith("jre", StringComparison.OrdinalIgnoreCase)
|
||||||
|
|| leaf.Equals("jdk", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
queue.Enqueue((child, depth + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<string> CollectRelatedLibDirs(string primaryLibDir, string searchRoot)
|
||||||
|
{
|
||||||
|
HashSet<string> dirs = new(StringComparer.OrdinalIgnoreCase) { primaryLibDir };
|
||||||
|
|
||||||
|
// Sibling-Libs oft: MQ/lib + ESB/lib + common/lib
|
||||||
|
string? parent = Directory.GetParent(primaryLibDir)?.FullName;
|
||||||
|
if (!string.IsNullOrWhiteSpace(parent))
|
||||||
|
{
|
||||||
|
foreach (string sibling in new[]
|
||||||
|
{
|
||||||
|
Path.Combine(parent, "lib"),
|
||||||
|
Path.Combine(parent, "common", "lib"),
|
||||||
|
Path.Combine(parent, "client", "lib")
|
||||||
|
})
|
||||||
|
{
|
||||||
|
if (Directory.Exists(sibling))
|
||||||
|
{
|
||||||
|
dirs.Add(sibling);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string? grand = Directory.GetParent(parent)?.FullName;
|
||||||
|
if (!string.IsNullOrWhiteSpace(grand))
|
||||||
|
{
|
||||||
|
foreach (string nested in EnumerateLikelyLibRoots(grand))
|
||||||
|
{
|
||||||
|
dirs.Add(nested);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Directory.Exists(searchRoot))
|
||||||
|
{
|
||||||
|
foreach (string nested in EnumerateLikelyLibRoots(searchRoot))
|
||||||
|
{
|
||||||
|
dirs.Add(nested);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dirs.Where(Directory.Exists).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string? BuildClasspathFromLibDirs(IEnumerable<string> libDirs)
|
||||||
|
{
|
||||||
|
HashSet<string> jarFiles = new(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
foreach (string dir in libDirs)
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(dir))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
foreach (string jar in Directory.EnumerateFiles(dir, "*.jar", SearchOption.TopDirectoryOnly))
|
||||||
|
{
|
||||||
|
jarFiles.Add(jar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignore unreadable dirs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<string> entries = jarFiles
|
||||||
|
.OrderBy(j => j, StringComparer.OrdinalIgnoreCase)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
if (entries.Count == 0)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Classpath-Länge begrenzen: zu viele Einträge → CreateProcess-Fehler
|
||||||
|
if (entries.Count > 250)
|
||||||
|
{
|
||||||
|
entries = entries.Take(250).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Join(Path.PathSeparator, entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<string> EnumerateLikelyLibRoots(string root)
|
private static IEnumerable<string> EnumerateLikelyLibRoots(string root)
|
||||||
@@ -698,44 +905,44 @@ public sealed class SonicMfApiExecutor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool DirectoryHasSonicClientJars(string path)
|
/// <summary>
|
||||||
|
/// Strikt: mindestens ein MF/Management-Client-JAR (nicht irgendein JAR-Ordner).
|
||||||
|
/// </summary>
|
||||||
|
private static bool DirectoryHasRequiredSonicClientJars(string path, out string? detail)
|
||||||
{
|
{
|
||||||
|
detail = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string[] jars = Directory.EnumerateFiles(path, "*.jar", SearchOption.TopDirectoryOnly).ToArray();
|
string[] jars = Directory.EnumerateFiles(path, "*.jar", SearchOption.TopDirectoryOnly).ToArray();
|
||||||
if (jars.Length == 0)
|
if (jars.Length == 0)
|
||||||
{
|
{
|
||||||
|
detail = "keine *.jar";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bevorzugt echte Sonic-Client-Libs; sonst jeder JAR-Ordner als Fallback.
|
string[] strong =
|
||||||
string[] markers =
|
|
||||||
[
|
[
|
||||||
"mgmt_client", "mfcontext", "sonic_Client", "sonic_client", "mf_client", "Sonic"
|
"mgmt_client", "mfcontext", "sonic_Client", "sonic_client", "mf_client", "mf-client"
|
||||||
];
|
];
|
||||||
if (jars.Any(j => markers.Any(m =>
|
|
||||||
Path.GetFileName(j).Contains(m, StringComparison.OrdinalIgnoreCase))))
|
bool hasStrong = jars.Any(j =>
|
||||||
|
strong.Any(m => Path.GetFileName(j).Contains(m, StringComparison.OrdinalIgnoreCase)));
|
||||||
|
|
||||||
|
if (!hasStrong)
|
||||||
{
|
{
|
||||||
|
detail = $"{jars.Length} JARs, aber ohne mgmt_client/mfcontext/sonic_Client";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
return jars.Length > 0;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
{
|
||||||
|
detail = ex.Message;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string BuildClasspath(string libDir, string? extraEntry)
|
|
||||||
{
|
|
||||||
// Java-Classpath-Wildcard für alle JARs im Lib-Ordner
|
|
||||||
string jars = Path.Combine(libDir, "*");
|
|
||||||
return string.IsNullOrWhiteSpace(extraEntry)
|
|
||||||
? jars
|
|
||||||
: jars + Path.PathSeparator + extraEntry;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string? ResolveToolSourcePath()
|
private static string? ResolveToolSourcePath()
|
||||||
{
|
{
|
||||||
string[] candidates =
|
string[] candidates =
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
@echo off
|
||||||
|
REM Prueft ob JMSConnectorAddress mit den Sonic-Client-JARs ladbar ist.
|
||||||
|
set LIB=C:\DEV\MQ10.0\lib
|
||||||
|
set JAVA=C:\Program Files (x86)\Java\jre1.8.0_501\bin\java.exe
|
||||||
|
|
||||||
|
if not exist "%JAVA%" (
|
||||||
|
echo Java nicht gefunden: %JAVA%
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
if not exist "%LIB%\mfcontext.jar" (
|
||||||
|
echo mfcontext.jar fehlt unter %LIB%
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
set CP=%LIB%\mgmt_client.jar;%LIB%\mgmt_config.jar;%LIB%\sonic_mgmt_client.jar;%LIB%\mfcontext.jar;%LIB%\sonic_Client.jar;%LIB%\sonic_Client_ext.jar
|
||||||
|
|
||||||
|
echo Java: %JAVA%
|
||||||
|
echo CP: %CP%
|
||||||
|
echo.
|
||||||
|
|
||||||
|
"%JAVA%" -cp "%CP%" -version
|
||||||
|
echo.
|
||||||
|
|
||||||
|
"%JAVA%" -cp "%CP%" com.sonicsw.mf.jmx.client.JMSConnectorAddress 2>&1
|
||||||
|
echo ExitCode=%ERRORLEVEL%
|
||||||
|
echo.
|
||||||
|
echo Erwartet: oft "main method" / NoSuchMethodError ODER Usage - Hauptsache KEIN ClassNotFoundException.
|
||||||
|
exit /b 0
|
||||||
@@ -16,9 +16,9 @@
|
|||||||
"SonicHome": "C:\\DEV\\MQ10.0",
|
"SonicHome": "C:\\DEV\\MQ10.0",
|
||||||
"JavaHome": "C:\\Program Files (x86)\\Java\\jre1.8.0_501",
|
"JavaHome": "C:\\Program Files (x86)\\Java\\jre1.8.0_501",
|
||||||
"JavaPath": "C:\\Program Files (x86)\\Java\\jre1.8.0_501\\bin\\java.exe",
|
"JavaPath": "C:\\Program Files (x86)\\Java\\jre1.8.0_501\\bin\\java.exe",
|
||||||
"MfClientLibPath": "",
|
"MfClientLibPath": "C:\\DEV\\MQ10.0\\lib",
|
||||||
"KnownContainers": [
|
"KnownContainers": [
|
||||||
"DE-Test"
|
"ct-ZADBService"
|
||||||
],
|
],
|
||||||
"WinRmUsername": "",
|
"WinRmUsername": "",
|
||||||
"WinRmPassword": "",
|
"WinRmPassword": "",
|
||||||
|
|||||||
Reference in New Issue
Block a user