Add Sonic container scan with manual multi-select after system setup.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,303 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using System.Text;
|
||||||
|
using ZA.CoreService.ESBCertificateManager.Models;
|
||||||
|
|
||||||
|
namespace ZA.CoreService.ESBCertificateManager.Services;
|
||||||
|
|
||||||
|
public sealed class SonicContainerScanner
|
||||||
|
{
|
||||||
|
private readonly RuntimeSettings _runtimeSettings;
|
||||||
|
|
||||||
|
public SonicContainerScanner(RuntimeSettings runtimeSettings)
|
||||||
|
{
|
||||||
|
_runtimeSettings = runtimeSettings
|
||||||
|
?? throw new ArgumentNullException(nameof(runtimeSettings));
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<ContainerScanResult> ScanAsync(
|
||||||
|
SonicSystemOption system,
|
||||||
|
string userName,
|
||||||
|
string secret,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
ArgumentNullException.ThrowIfNull(system);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(userName))
|
||||||
|
{
|
||||||
|
return ContainerScanResult.Failed(
|
||||||
|
"Der Sonic-Benutzername fehlt.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(secret))
|
||||||
|
{
|
||||||
|
return ContainerScanResult.Failed(
|
||||||
|
"Das Sonic-Kennwort fehlt.");
|
||||||
|
}
|
||||||
|
|
||||||
|
string javaPath =
|
||||||
|
PathResolver.ResolvePath(
|
||||||
|
_runtimeSettings.JavaExecutablePath);
|
||||||
|
|
||||||
|
string libraryPath =
|
||||||
|
PathResolver.ResolvePath(
|
||||||
|
_runtimeSettings.SonicClientLibraryPath);
|
||||||
|
|
||||||
|
string? toolsPath = ResolveToolsDirectory();
|
||||||
|
|
||||||
|
if (!File.Exists(javaPath))
|
||||||
|
{
|
||||||
|
return ContainerScanResult.Failed(
|
||||||
|
$"Java wurde nicht gefunden: {javaPath}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Directory.Exists(libraryPath))
|
||||||
|
{
|
||||||
|
return ContainerScanResult.Failed(
|
||||||
|
$"Der Sonic-JAR-Ordner wurde nicht gefunden: {libraryPath}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toolsPath is null)
|
||||||
|
{
|
||||||
|
return ContainerScanResult.Failed(
|
||||||
|
"SonicMfContainerTool.class wurde nicht gefunden.");
|
||||||
|
}
|
||||||
|
|
||||||
|
string[] jars =
|
||||||
|
Directory.GetFiles(
|
||||||
|
libraryPath,
|
||||||
|
"*.jar",
|
||||||
|
SearchOption.TopDirectoryOnly);
|
||||||
|
|
||||||
|
if (jars.Length == 0)
|
||||||
|
{
|
||||||
|
return ContainerScanResult.Failed(
|
||||||
|
"Im Sonic-Client-Ordner wurden keine JAR-Dateien gefunden.");
|
||||||
|
}
|
||||||
|
|
||||||
|
string classpath =
|
||||||
|
toolsPath
|
||||||
|
+ Path.PathSeparator
|
||||||
|
+ string.Join(
|
||||||
|
Path.PathSeparator,
|
||||||
|
jars.OrderBy(
|
||||||
|
Path.GetFileName,
|
||||||
|
StringComparer.OrdinalIgnoreCase));
|
||||||
|
|
||||||
|
ProcessStartInfo startInfo = new()
|
||||||
|
{
|
||||||
|
FileName = javaPath,
|
||||||
|
WorkingDirectory = toolsPath,
|
||||||
|
UseShellExecute = false,
|
||||||
|
RedirectStandardOutput = true,
|
||||||
|
RedirectStandardError = true,
|
||||||
|
StandardOutputEncoding = Encoding.UTF8,
|
||||||
|
StandardErrorEncoding = Encoding.UTF8,
|
||||||
|
CreateNoWindow = true
|
||||||
|
};
|
||||||
|
|
||||||
|
startInfo.ArgumentList.Add("-cp");
|
||||||
|
startInfo.ArgumentList.Add(classpath);
|
||||||
|
startInfo.ArgumentList.Add("SonicMfContainerTool");
|
||||||
|
startInfo.ArgumentList.Add("list");
|
||||||
|
startInfo.ArgumentList.Add("--domain");
|
||||||
|
startInfo.ArgumentList.Add(system.DomainName);
|
||||||
|
startInfo.ArgumentList.Add("--url");
|
||||||
|
startInfo.ArgumentList.Add(system.ConnectionUrl);
|
||||||
|
startInfo.ArgumentList.Add("--user");
|
||||||
|
startInfo.ArgumentList.Add(userName.Trim());
|
||||||
|
startInfo.ArgumentList.Add("--timeout");
|
||||||
|
startInfo.ArgumentList.Add("45");
|
||||||
|
|
||||||
|
startInfo.Environment["ESB_SONIC_PASSWORD"] = secret;
|
||||||
|
|
||||||
|
using Process process = new()
|
||||||
|
{
|
||||||
|
StartInfo = startInfo
|
||||||
|
};
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!process.Start())
|
||||||
|
{
|
||||||
|
return ContainerScanResult.Failed(
|
||||||
|
"Der Java-Prozess konnte nicht gestartet werden.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return ContainerScanResult.Failed(
|
||||||
|
$"Java konnte nicht gestartet werden: {ex.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
Task<string> standardOutputTask =
|
||||||
|
process.StandardOutput.ReadToEndAsync();
|
||||||
|
|
||||||
|
Task<string> standardErrorTask =
|
||||||
|
process.StandardError.ReadToEndAsync();
|
||||||
|
|
||||||
|
using CancellationTokenSource timeoutSource =
|
||||||
|
CancellationTokenSource.CreateLinkedTokenSource(
|
||||||
|
cancellationToken);
|
||||||
|
|
||||||
|
timeoutSource.CancelAfter(TimeSpan.FromSeconds(50));
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await process.WaitForExitAsync(timeoutSource.Token);
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
when (!cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
TryKill(process);
|
||||||
|
|
||||||
|
return ContainerScanResult.Failed(
|
||||||
|
"Der Container-Scan hat das Zeitlimit überschritten.");
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
TryKill(process);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
string standardOutput =
|
||||||
|
(await standardOutputTask).Trim();
|
||||||
|
|
||||||
|
string standardError =
|
||||||
|
(await standardErrorTask).Trim();
|
||||||
|
|
||||||
|
string combined =
|
||||||
|
string.Join(
|
||||||
|
Environment.NewLine,
|
||||||
|
new[] { standardOutput, standardError }
|
||||||
|
.Where(value => !string.IsNullOrWhiteSpace(value)));
|
||||||
|
|
||||||
|
bool success =
|
||||||
|
process.ExitCode == 0
|
||||||
|
&& combined.Contains(
|
||||||
|
"OK:ContainerListEnd",
|
||||||
|
StringComparison.OrdinalIgnoreCase)
|
||||||
|
&& !combined.Contains(
|
||||||
|
"ERROR:",
|
||||||
|
StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
return ContainerScanResult.Failed(
|
||||||
|
ExtractError(combined)
|
||||||
|
?? $"Container-Scan fehlgeschlagen, ExitCode={process.ExitCode}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<string> containers = [];
|
||||||
|
|
||||||
|
foreach (string line in standardOutput.Split(
|
||||||
|
['\r', '\n'],
|
||||||
|
StringSplitOptions.RemoveEmptyEntries))
|
||||||
|
{
|
||||||
|
const string prefix = "CONTAINER=";
|
||||||
|
|
||||||
|
if (!line.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
string name = line[prefix.Length..].Trim();
|
||||||
|
|
||||||
|
if (name.Length > 0
|
||||||
|
&& !containers.Contains(name, StringComparer.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
containers.Add(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
containers.Sort(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
return ContainerScanResult.Successful(containers);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string? ResolveToolsDirectory()
|
||||||
|
{
|
||||||
|
string baseDirectory = AppContext.BaseDirectory;
|
||||||
|
|
||||||
|
string[] candidates =
|
||||||
|
[
|
||||||
|
Path.Combine(baseDirectory, "Tools"),
|
||||||
|
Path.Combine(baseDirectory, "..", "..", "..", "Tools"),
|
||||||
|
Path.Combine(
|
||||||
|
Directory.GetCurrentDirectory(),
|
||||||
|
"Tools")
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach (string candidate in candidates)
|
||||||
|
{
|
||||||
|
string fullPath = Path.GetFullPath(candidate);
|
||||||
|
string classFile = Path.Combine(
|
||||||
|
fullPath,
|
||||||
|
"SonicMfContainerTool.class");
|
||||||
|
|
||||||
|
if (File.Exists(classFile))
|
||||||
|
{
|
||||||
|
return fullPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string? ExtractError(string output)
|
||||||
|
{
|
||||||
|
foreach (string line in output.Split(
|
||||||
|
['\r', '\n'],
|
||||||
|
StringSplitOptions.RemoveEmptyEntries))
|
||||||
|
{
|
||||||
|
if (line.StartsWith("ERROR:", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return line["ERROR:".Length..].Trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.IsNullOrWhiteSpace(output) ? null : output;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void TryKill(Process process)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!process.HasExited)
|
||||||
|
{
|
||||||
|
process.Kill(entireProcessTree: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class ContainerScanResult
|
||||||
|
{
|
||||||
|
public bool Success { get; init; }
|
||||||
|
|
||||||
|
public string Message { get; init; } = string.Empty;
|
||||||
|
|
||||||
|
public IReadOnlyList<string> Containers { get; init; } = [];
|
||||||
|
|
||||||
|
public static ContainerScanResult Successful(
|
||||||
|
IReadOnlyList<string> containers)
|
||||||
|
{
|
||||||
|
return new ContainerScanResult
|
||||||
|
{
|
||||||
|
Success = true,
|
||||||
|
Message = $"{containers.Count} Container gefunden.",
|
||||||
|
Containers = containers
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ContainerScanResult Failed(string message)
|
||||||
|
{
|
||||||
|
return new ContainerScanResult
|
||||||
|
{
|
||||||
|
Success = false,
|
||||||
|
Message = message
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,432 @@
|
|||||||
|
using ZA.CoreService.ESBCertificateManager.Models;
|
||||||
|
using ZA.CoreService.ESBCertificateManager.Services;
|
||||||
|
|
||||||
|
namespace ZA.CoreService.ESBCertificateManager.Setup;
|
||||||
|
|
||||||
|
public sealed class SelectContainersForm : Form
|
||||||
|
{
|
||||||
|
private readonly SetupCoordinator _coordinator;
|
||||||
|
private readonly SonicSystemOption _system;
|
||||||
|
private readonly SonicContainerScanner _scanner;
|
||||||
|
|
||||||
|
private readonly ComboBox _cmbCompany;
|
||||||
|
private readonly CheckedListBox _lstContainers;
|
||||||
|
private readonly TextBox _txtManual;
|
||||||
|
private readonly TextBox _txtUser;
|
||||||
|
private readonly TextBox _txtPassword;
|
||||||
|
private readonly Label _lblStatus;
|
||||||
|
private readonly Button _btnScan;
|
||||||
|
private readonly Button _btnSave;
|
||||||
|
private bool _running;
|
||||||
|
|
||||||
|
public int SavedCount { get; private set; }
|
||||||
|
|
||||||
|
public SelectContainersForm(
|
||||||
|
SetupCoordinator coordinator,
|
||||||
|
SonicSystemOption system)
|
||||||
|
{
|
||||||
|
_coordinator = coordinator;
|
||||||
|
_system = system;
|
||||||
|
_scanner = new SonicContainerScanner(coordinator.Settings.Runtime);
|
||||||
|
|
||||||
|
Text = "Container auswählen";
|
||||||
|
StartPosition = FormStartPosition.CenterParent;
|
||||||
|
FormBorderStyle = FormBorderStyle.FixedDialog;
|
||||||
|
MaximizeBox = false;
|
||||||
|
MinimizeBox = false;
|
||||||
|
ShowInTaskbar = false;
|
||||||
|
ClientSize = new Size(640, 620);
|
||||||
|
BackColor = SettingsUi.Background;
|
||||||
|
ForeColor = SettingsUi.Text;
|
||||||
|
Font = new Font("Segoe UI", 10f);
|
||||||
|
|
||||||
|
Label title = new()
|
||||||
|
{
|
||||||
|
Text = "Container für System",
|
||||||
|
Location = new Point(28, 20),
|
||||||
|
AutoSize = true,
|
||||||
|
Font = new Font("Segoe UI Semibold", 18f, FontStyle.Bold),
|
||||||
|
ForeColor = SettingsUi.Text
|
||||||
|
};
|
||||||
|
|
||||||
|
Label subtitle = new()
|
||||||
|
{
|
||||||
|
Text =
|
||||||
|
$"{system.ConnectionName} · {system.ConnectionUrl}"
|
||||||
|
+ Environment.NewLine
|
||||||
|
+ "Scan von Sonic oder manuell eintragen, dann übernehmen.",
|
||||||
|
Location = new Point(30, 54),
|
||||||
|
Size = new Size(580, 40),
|
||||||
|
ForeColor = SettingsUi.Muted
|
||||||
|
};
|
||||||
|
|
||||||
|
Panel card = SettingsUi.CreateCard();
|
||||||
|
card.Location = new Point(28, 110);
|
||||||
|
card.Size = new Size(584, 430);
|
||||||
|
card.Paint += SettingsUi.PaintCardBorder;
|
||||||
|
|
||||||
|
_cmbCompany = SettingsUi.CreateComboBox();
|
||||||
|
_lstContainers = new CheckedListBox
|
||||||
|
{
|
||||||
|
BackColor = Color.FromArgb(12, 28, 48),
|
||||||
|
ForeColor = SettingsUi.Text,
|
||||||
|
BorderStyle = BorderStyle.FixedSingle,
|
||||||
|
CheckOnClick = true,
|
||||||
|
Font = new Font("Segoe UI", 10f)
|
||||||
|
};
|
||||||
|
|
||||||
|
_txtManual = SettingsUi.CreateTextBox();
|
||||||
|
_txtUser = SettingsUi.CreateTextBox();
|
||||||
|
_txtPassword = SettingsUi.CreateTextBox();
|
||||||
|
_txtPassword.UseSystemPasswordChar = true;
|
||||||
|
|
||||||
|
AddField(card, "Company", _cmbCompany, 18, 16, 540);
|
||||||
|
AddField(card, "Gefundene / gewählte Container", _lstContainers, 18, 76, 540, 150);
|
||||||
|
|
||||||
|
Label manualLabel = SettingsUi.CreateFieldLabel("Manuell hinzufügen");
|
||||||
|
manualLabel.Location = new Point(18, 240);
|
||||||
|
_txtManual.Location = new Point(18, 262);
|
||||||
|
_txtManual.Width = 400;
|
||||||
|
|
||||||
|
Button btnAddManual = SettingsUi.CreateGhostButton("+");
|
||||||
|
btnAddManual.Location = new Point(430, 260);
|
||||||
|
btnAddManual.Size = new Size(50, 32);
|
||||||
|
btnAddManual.Click += (_, _) => AddManualContainer();
|
||||||
|
|
||||||
|
Button btnSuggest = SettingsUi.CreateGhostButton("ct-ZADBService");
|
||||||
|
btnSuggest.Location = new Point(490, 260);
|
||||||
|
btnSuggest.Size = new Size(68, 32);
|
||||||
|
btnSuggest.Font = new Font("Segoe UI", 7.5f, FontStyle.Bold);
|
||||||
|
btnSuggest.Click += (_, _) =>
|
||||||
|
{
|
||||||
|
_txtManual.Text = "ct-ZADBService";
|
||||||
|
AddManualContainer();
|
||||||
|
};
|
||||||
|
|
||||||
|
AddField(card, "Sonic-Benutzer (für Scan)", _txtUser, 18, 308, 250);
|
||||||
|
AddField(card, "Kennwort", _txtPassword, 288, 308, 270);
|
||||||
|
|
||||||
|
_btnScan = SettingsUi.CreatePrimaryButton("Von Sonic scannen");
|
||||||
|
_btnScan.Location = new Point(18, 375);
|
||||||
|
_btnScan.Size = new Size(200, 36);
|
||||||
|
_btnScan.Click += async (_, _) => await ScanAsync();
|
||||||
|
|
||||||
|
_lblStatus = new Label
|
||||||
|
{
|
||||||
|
Location = new Point(230, 380),
|
||||||
|
Size = new Size(330, 30),
|
||||||
|
ForeColor = SettingsUi.Muted
|
||||||
|
};
|
||||||
|
|
||||||
|
card.Controls.Add(manualLabel);
|
||||||
|
card.Controls.Add(_txtManual);
|
||||||
|
card.Controls.Add(btnAddManual);
|
||||||
|
card.Controls.Add(btnSuggest);
|
||||||
|
card.Controls.Add(_btnScan);
|
||||||
|
card.Controls.Add(_lblStatus);
|
||||||
|
|
||||||
|
_btnSave = SettingsUi.CreatePrimaryButton("Auswahl speichern");
|
||||||
|
_btnSave.Location = new Point(352, 555);
|
||||||
|
_btnSave.Size = new Size(260, 42);
|
||||||
|
_btnSave.Click += async (_, _) => await SaveAsync();
|
||||||
|
|
||||||
|
Button skip = SettingsUi.CreateGhostButton("Später");
|
||||||
|
skip.Location = new Point(230, 555);
|
||||||
|
skip.Size = new Size(110, 42);
|
||||||
|
skip.Click += (_, _) =>
|
||||||
|
{
|
||||||
|
DialogResult = DialogResult.Cancel;
|
||||||
|
Close();
|
||||||
|
};
|
||||||
|
|
||||||
|
Controls.Add(title);
|
||||||
|
Controls.Add(subtitle);
|
||||||
|
Controls.Add(card);
|
||||||
|
Controls.Add(skip);
|
||||||
|
Controls.Add(_btnSave);
|
||||||
|
|
||||||
|
Shown += async (_, _) => await InitializeAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task InitializeAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IReadOnlyList<CompanyOption> companies =
|
||||||
|
await _coordinator.LoadCompaniesAsync();
|
||||||
|
|
||||||
|
_cmbCompany.Items.Clear();
|
||||||
|
|
||||||
|
foreach (CompanyOption company in companies)
|
||||||
|
{
|
||||||
|
_cmbCompany.Items.Add(company);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_cmbCompany.Items.Count > 0)
|
||||||
|
{
|
||||||
|
int deIndex = 0;
|
||||||
|
|
||||||
|
for (int index = 0; index < companies.Count; index++)
|
||||||
|
{
|
||||||
|
if (string.Equals(
|
||||||
|
companies[index].CompanyCode,
|
||||||
|
"DE",
|
||||||
|
StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
deIndex = index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_cmbCompany.SelectedIndex = deIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
IReadOnlyList<SonicCredentialProfile> profiles =
|
||||||
|
await _coordinator.LoadCredentialsAsync(
|
||||||
|
_system.SonicConnectionId);
|
||||||
|
|
||||||
|
SonicCredentialProfile? profile =
|
||||||
|
profiles.FirstOrDefault(item => item.IsDefault)
|
||||||
|
?? profiles.FirstOrDefault();
|
||||||
|
|
||||||
|
if (profile is not null)
|
||||||
|
{
|
||||||
|
_txtUser.Text = profile.UserName;
|
||||||
|
_txtPassword.Text = profile.Secret;
|
||||||
|
_lblStatus.Text =
|
||||||
|
"Profil geladen — Scan möglich.";
|
||||||
|
_lblStatus.ForeColor = SettingsUi.Green;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_lblStatus.Text =
|
||||||
|
"Kein Profil — Benutzer/Kennwort für Scan eingeben oder manuell.";
|
||||||
|
_lblStatus.ForeColor = SettingsUi.Gold;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bereits vorhandene Container vorselektieren
|
||||||
|
IReadOnlyList<ContainerOption> existing =
|
||||||
|
await _coordinator.LoadContainersAsync(
|
||||||
|
_system.SonicConnectionId);
|
||||||
|
|
||||||
|
foreach (ContainerOption container in existing)
|
||||||
|
{
|
||||||
|
AddContainerName(container.ContainerName, check: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_lblStatus.Text = ex.Message;
|
||||||
|
_lblStatus.ForeColor = SettingsUi.Red;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddManualContainer()
|
||||||
|
{
|
||||||
|
string name = _txtManual.Text.Trim();
|
||||||
|
|
||||||
|
if (name.Length == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddContainerName(name, check: true);
|
||||||
|
_txtManual.Clear();
|
||||||
|
_txtManual.Focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddContainerName(string name, bool check)
|
||||||
|
{
|
||||||
|
for (int index = 0; index < _lstContainers.Items.Count; index++)
|
||||||
|
{
|
||||||
|
if (string.Equals(
|
||||||
|
_lstContainers.Items[index]?.ToString(),
|
||||||
|
name,
|
||||||
|
StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
_lstContainers.SetItemChecked(index, check);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int added = _lstContainers.Items.Add(name);
|
||||||
|
_lstContainers.SetItemChecked(added, check);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ScanAsync()
|
||||||
|
{
|
||||||
|
if (_running)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_running = true;
|
||||||
|
_btnScan.Enabled = false;
|
||||||
|
_btnSave.Enabled = false;
|
||||||
|
Cursor = Cursors.WaitCursor;
|
||||||
|
_lblStatus.Text = "Scanne Domain…";
|
||||||
|
_lblStatus.ForeColor = SettingsUi.Muted;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ContainerScanResult result =
|
||||||
|
await _scanner.ScanAsync(
|
||||||
|
_system,
|
||||||
|
_txtUser.Text,
|
||||||
|
_txtPassword.Text);
|
||||||
|
|
||||||
|
if (!result.Success)
|
||||||
|
{
|
||||||
|
_lblStatus.Text = result.Message;
|
||||||
|
_lblStatus.ForeColor = SettingsUi.Red;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string container in result.Containers)
|
||||||
|
{
|
||||||
|
AddContainerName(container, check: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
_lblStatus.Text =
|
||||||
|
result.Containers.Count == 0
|
||||||
|
? "Scan OK, aber keine Container gefunden — bitte manuell."
|
||||||
|
: $"{result.Containers.Count} Container gescannt und vorausgewählt.";
|
||||||
|
|
||||||
|
_lblStatus.ForeColor =
|
||||||
|
result.Containers.Count == 0
|
||||||
|
? SettingsUi.Gold
|
||||||
|
: SettingsUi.Green;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_lblStatus.Text = ex.Message;
|
||||||
|
_lblStatus.ForeColor = SettingsUi.Red;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_running = false;
|
||||||
|
_btnScan.Enabled = true;
|
||||||
|
_btnSave.Enabled = true;
|
||||||
|
Cursor = Cursors.Default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SaveAsync()
|
||||||
|
{
|
||||||
|
if (_running)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_cmbCompany.SelectedItem is not CompanyOption company)
|
||||||
|
{
|
||||||
|
MessageBox.Show(
|
||||||
|
this,
|
||||||
|
"Bitte eine Company wählen.",
|
||||||
|
"Container",
|
||||||
|
MessageBoxButtons.OK,
|
||||||
|
MessageBoxIcon.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<string> selected = _lstContainers.CheckedItems
|
||||||
|
.Cast<object>()
|
||||||
|
.Select(item => item.ToString() ?? string.Empty)
|
||||||
|
.Where(name => name.Length > 0)
|
||||||
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
if (selected.Count == 0)
|
||||||
|
{
|
||||||
|
MessageBox.Show(
|
||||||
|
this,
|
||||||
|
"Bitte mindestens einen Container angehakt lassen "
|
||||||
|
+ "oder manuell hinzufügen.",
|
||||||
|
"Container",
|
||||||
|
MessageBoxButtons.OK,
|
||||||
|
MessageBoxIcon.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_running = true;
|
||||||
|
_btnSave.Enabled = false;
|
||||||
|
Cursor = Cursors.WaitCursor;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IReadOnlyList<ContainerOption> existing =
|
||||||
|
await _coordinator.LoadContainersAsync(
|
||||||
|
_system.SonicConnectionId);
|
||||||
|
|
||||||
|
HashSet<string> existingNames = existing
|
||||||
|
.Select(item => item.ContainerName)
|
||||||
|
.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
int created = 0;
|
||||||
|
|
||||||
|
foreach (string containerName in selected)
|
||||||
|
{
|
||||||
|
if (existingNames.Contains(containerName))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
await _coordinator.AddSonicContainerAsync(
|
||||||
|
company.CompanyId,
|
||||||
|
_system.SonicConnectionId,
|
||||||
|
containerName,
|
||||||
|
containerDisplayName: null,
|
||||||
|
restartTimeoutSeconds: 180);
|
||||||
|
|
||||||
|
created++;
|
||||||
|
}
|
||||||
|
|
||||||
|
SavedCount = created;
|
||||||
|
|
||||||
|
MessageBox.Show(
|
||||||
|
this,
|
||||||
|
created == 0
|
||||||
|
? "Alle gewählten Container waren bereits vorhanden."
|
||||||
|
: $"{created} Container gespeichert und geprüft.",
|
||||||
|
"Prüfung OK",
|
||||||
|
MessageBoxButtons.OK,
|
||||||
|
MessageBoxIcon.Information);
|
||||||
|
|
||||||
|
DialogResult = DialogResult.OK;
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show(
|
||||||
|
this,
|
||||||
|
ex.Message,
|
||||||
|
"Container",
|
||||||
|
MessageBoxButtons.OK,
|
||||||
|
MessageBoxIcon.Error);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_running = false;
|
||||||
|
_btnSave.Enabled = true;
|
||||||
|
Cursor = Cursors.Default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AddField(
|
||||||
|
Control parent,
|
||||||
|
string label,
|
||||||
|
Control input,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
int width,
|
||||||
|
int height = 30)
|
||||||
|
{
|
||||||
|
Label fieldLabel = SettingsUi.CreateFieldLabel(label);
|
||||||
|
fieldLabel.Location = new Point(x, y);
|
||||||
|
input.Location = new Point(x, y + 22);
|
||||||
|
input.Width = width;
|
||||||
|
input.Height = height;
|
||||||
|
parent.Controls.Add(fieldLabel);
|
||||||
|
parent.Controls.Add(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -381,7 +381,9 @@ public sealed class SetupWizardForm : Form
|
|||||||
|
|
||||||
Panel toolbar = CreateToolbar(
|
Panel toolbar = CreateToolbar(
|
||||||
"+ Container hinzufügen",
|
"+ Container hinzufügen",
|
||||||
async () => await AddContainerAsync());
|
async () => await AddContainerAsync(),
|
||||||
|
secondaryText: "Von Sonic scannen",
|
||||||
|
onSecondary: async () => await ScanContainersForSelectedSystemAsync());
|
||||||
|
|
||||||
_lvContainers = SettingsUi.CreateListView();
|
_lvContainers = SettingsUi.CreateListView();
|
||||||
_lvContainers.Dock = DockStyle.Fill;
|
_lvContainers.Dock = DockStyle.Fill;
|
||||||
@@ -418,7 +420,9 @@ public sealed class SetupWizardForm : Form
|
|||||||
|
|
||||||
private Panel CreateToolbar(
|
private Panel CreateToolbar(
|
||||||
string addButtonText,
|
string addButtonText,
|
||||||
Func<Task> onAdd)
|
Func<Task> onAdd,
|
||||||
|
string? secondaryText = null,
|
||||||
|
Func<Task>? onSecondary = null)
|
||||||
{
|
{
|
||||||
Panel toolbar = new()
|
Panel toolbar = new()
|
||||||
{
|
{
|
||||||
@@ -433,6 +437,16 @@ public sealed class SetupWizardForm : Form
|
|||||||
add.Width = 230;
|
add.Width = 230;
|
||||||
add.Click += async (_, _) => await onAdd();
|
add.Click += async (_, _) => await onAdd();
|
||||||
|
|
||||||
|
if (secondaryText is not null && onSecondary is not null)
|
||||||
|
{
|
||||||
|
Button secondary = SettingsUi.CreateGhostButton(secondaryText);
|
||||||
|
secondary.Dock = DockStyle.Left;
|
||||||
|
secondary.Width = 180;
|
||||||
|
secondary.Margin = new Padding(8, 0, 0, 0);
|
||||||
|
secondary.Click += async (_, _) => await onSecondary();
|
||||||
|
toolbar.Controls.Add(secondary);
|
||||||
|
}
|
||||||
|
|
||||||
toolbar.Controls.Add(add);
|
toolbar.Controls.Add(add);
|
||||||
return toolbar;
|
return toolbar;
|
||||||
}
|
}
|
||||||
@@ -692,6 +706,78 @@ public sealed class SetupWizardForm : Form
|
|||||||
"Prüfung OK",
|
"Prüfung OK",
|
||||||
MessageBoxButtons.OK,
|
MessageBoxButtons.OK,
|
||||||
MessageBoxIcon.Information);
|
MessageBoxIcon.Information);
|
||||||
|
|
||||||
|
SonicSystemOption? createdSystem = _systems
|
||||||
|
.FirstOrDefault(system =>
|
||||||
|
system.SonicConnectionId == createdId);
|
||||||
|
|
||||||
|
if (createdSystem is null
|
||||||
|
&& _lvSystems.SelectedItems.Count > 0)
|
||||||
|
{
|
||||||
|
createdSystem =
|
||||||
|
_lvSystems.SelectedItems[0].Tag as SonicSystemOption;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (createdSystem is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DialogResult next = MessageBox.Show(
|
||||||
|
this,
|
||||||
|
"Container jetzt per Sonic-Scan oder manuell zuordnen?",
|
||||||
|
"Container",
|
||||||
|
MessageBoxButtons.YesNo,
|
||||||
|
MessageBoxIcon.Question);
|
||||||
|
|
||||||
|
if (next != DialogResult.Yes)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
using SelectContainersForm selectForm =
|
||||||
|
new(_coordinator, createdSystem);
|
||||||
|
|
||||||
|
if (selectForm.ShowDialog(this) == DialogResult.OK)
|
||||||
|
{
|
||||||
|
await LoadContainersListAsync();
|
||||||
|
await RefreshAllAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ScanContainersForSelectedSystemAsync()
|
||||||
|
{
|
||||||
|
SonicSystemOption? system = null;
|
||||||
|
|
||||||
|
if (_lvSystems.SelectedItems.Count > 0)
|
||||||
|
{
|
||||||
|
system = _lvSystems.SelectedItems[0].Tag as SonicSystemOption;
|
||||||
|
}
|
||||||
|
|
||||||
|
system ??= _systems.FirstOrDefault();
|
||||||
|
|
||||||
|
if (system is null)
|
||||||
|
{
|
||||||
|
// Systeme-Liste ggf. nachladen
|
||||||
|
await LoadSystemsListAsync();
|
||||||
|
system = _systems.FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (system is null)
|
||||||
|
{
|
||||||
|
ShowWarning(
|
||||||
|
"Bitte zuerst ein Sonic-System anlegen oder auswählen.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
using SelectContainersForm selectForm =
|
||||||
|
new(_coordinator, system);
|
||||||
|
|
||||||
|
if (selectForm.ShowDialog(this) == DialogResult.OK)
|
||||||
|
{
|
||||||
|
await LoadContainersListAsync();
|
||||||
|
await RefreshAllAsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task AddContainerAsync()
|
private async Task AddContainerAsync()
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,68 +1,72 @@
|
|||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.management.ObjectName;
|
import javax.management.ObjectName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sonic-MfApi-Hilfsprogramm.
|
* Sonic-MfApi-Hilfsprogramm.
|
||||||
*
|
*
|
||||||
* Unterstützte Befehle:
|
* Befehle:
|
||||||
*
|
* validate - Anmeldung + lesender Container-Zugriff
|
||||||
* validate
|
* restart - Container neu starten (stop/restart)
|
||||||
* Prüft Anmeldung und lesenden Zugriff auf den Container.
|
* list - Container der Domain auflisten
|
||||||
* Es wird kein Neustart ausgeführt.
|
|
||||||
*
|
|
||||||
* restart
|
|
||||||
* Startet den angegebenen Container neu.
|
|
||||||
*
|
|
||||||
* Kompilierung mit Java 8:
|
|
||||||
*
|
*
|
||||||
* javac -source 8 -target 8 SonicMfContainerTool.java
|
* javac -source 8 -target 8 SonicMfContainerTool.java
|
||||||
*/
|
*/
|
||||||
public final class SonicMfConta*nerTool
|
public final class SonicMfContainerTool
|
||||||
{
|
{
|
||||||
public static final *tring TOOL_VERSION =
|
public static final String TOOL_VERSION =
|
||||||
"2026*07-27-validate-and-restart";
|
"2026-07-29-validate-restart-list";
|
||||||
|
|
||||||
*ublic static void main(String[] ar*s)
|
public static void main(String[] args)
|
||||||
{
|
{
|
||||||
info("ToolVersion*" + TOOL_VERSION);
|
info("ToolVersion=" + TOOL_VERSION);
|
||||||
|
|
||||||
try
|
try
|
||||||
* {
|
{
|
||||||
Args parsedArgu*ents = Args.parse(args);
|
Args parsedArguments = Args.parse(args);
|
||||||
|
|
||||||
* if (!"validate".equals(parsedAr*uments.command)
|
if (!"validate".equals(parsedArguments.command)
|
||||||
&&*!"restart".equals(parsedArguments.*ommand))
|
&& !"restart".equals(parsedArguments.command)
|
||||||
|
&& !"list".equals(parsedArguments.command))
|
||||||
{
|
{
|
||||||
* fail(
|
|
||||||
"Usa*e: SonicMfContainerTool "
|
|
||||||
* + "<validate|restart> "* + "--domain D *
|
|
||||||
+ "--url U "
|
|
||||||
* + "--user U "
|
|
||||||
* + "--container C*"
|
|
||||||
+ "[--timeout SEC]");
|
|
||||||
|
|
||||||
return;
|
|
||||||
* }
|
|
||||||
|
|
||||||
if (isBl*nk(parsedArguments.domain)
|
|
||||||
* || isBlank(parsedArguments*url)
|
|
||||||
|| isBlank(pa*sedArguments.user)
|
|
||||||
*|| isBlank(parsedArguments.contain*r))
|
|
||||||
{
|
|
||||||
*ail(
|
|
||||||
"domain, *rl, user und container sind Pflich*.");
|
|
||||||
|
|
||||||
return;
|
|
||||||
* }
|
|
||||||
|
|
||||||
if (isBlank(*arsedArguments.password))
|
|
||||||
* {
|
|
||||||
fail(
|
fail(
|
||||||
* "Das Sonic-Kennwort wurde nicht über "
|
"Usage: SonicMfContainerTool "
|
||||||
+ "ESB_SONIC_PASSWORD bereitgestellt.");
|
+ "<validate|restart|list> "
|
||||||
|
+ "--domain D "
|
||||||
|
+ "--url U "
|
||||||
|
+ "--user U "
|
||||||
|
+ "[--container C] "
|
||||||
|
+ "[--timeout SEC]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isBlank(parsedArguments.domain)
|
||||||
|
|| isBlank(parsedArguments.url)
|
||||||
|
|| isBlank(parsedArguments.user))
|
||||||
|
{
|
||||||
|
fail("domain, url und user sind Pflicht.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean needsContainer =
|
||||||
|
"validate".equals(parsedArguments.command)
|
||||||
|
|| "restart".equals(parsedArguments.command);
|
||||||
|
|
||||||
|
if (needsContainer
|
||||||
|
&& isBlank(parsedArguments.container))
|
||||||
|
{
|
||||||
|
fail("container ist Pflicht fuer validate/restart.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isBlank(parsedArguments.password))
|
||||||
|
{
|
||||||
|
fail(
|
||||||
|
"Das Sonic-Kennwort wurde nicht ueber "
|
||||||
|
+ "ESB_SONIC_PASSWORD bereitgestellt.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +82,13 @@ public final class SonicMfConta*nerTool
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if ("validate".equals(
|
if ("list".equals(parsedArguments.command))
|
||||||
|
{
|
||||||
|
listContainers(
|
||||||
|
connector,
|
||||||
|
parsedArguments.domain);
|
||||||
|
}
|
||||||
|
else if ("validate".equals(
|
||||||
parsedArguments.command))
|
parsedArguments.command))
|
||||||
{
|
{
|
||||||
validateConnection(
|
validateConnection(
|
||||||
@@ -102,7 +112,6 @@ public final class SonicMfConta*nerTool
|
|||||||
catch (Throwable throwable)
|
catch (Throwable throwable)
|
||||||
{
|
{
|
||||||
Throwable root = rootOf(throwable);
|
Throwable root = rootOf(throwable);
|
||||||
|
|
||||||
String message = root.getMessage();
|
String message = root.getMessage();
|
||||||
|
|
||||||
if (message == null)
|
if (message == null)
|
||||||
@@ -117,6 +126,115 @@ public final class SonicMfConta*nerTool
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void listContainers(
|
||||||
|
Object connector,
|
||||||
|
String domain)
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
Method queryNamesMethod =
|
||||||
|
findMethod(
|
||||||
|
connector.getClass(),
|
||||||
|
"queryNames",
|
||||||
|
new Class[]
|
||||||
|
{
|
||||||
|
ObjectName.class,
|
||||||
|
javax.management.QueryExp.class
|
||||||
|
});
|
||||||
|
|
||||||
|
if (queryNamesMethod == null)
|
||||||
|
{
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"queryNames(ObjectName, QueryExp) wurde nicht gefunden.");
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectName pattern =
|
||||||
|
new ObjectName("*:ID=AGENT");
|
||||||
|
|
||||||
|
Object rawResult = queryNamesMethod.invoke(
|
||||||
|
connector,
|
||||||
|
new Object[]
|
||||||
|
{
|
||||||
|
pattern,
|
||||||
|
null
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!(rawResult instanceof Set))
|
||||||
|
{
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"queryNames lieferte kein Set.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Set names = (Set) rawResult;
|
||||||
|
String domainPrefix = domain + ".";
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
System.out.println("OK:ContainerListBegin");
|
||||||
|
|
||||||
|
Iterator iterator = names.iterator();
|
||||||
|
|
||||||
|
while (iterator.hasNext())
|
||||||
|
{
|
||||||
|
Object entry = iterator.next();
|
||||||
|
|
||||||
|
if (!(entry instanceof ObjectName))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectName objectName = (ObjectName) entry;
|
||||||
|
String canonical = objectName.getCanonicalName();
|
||||||
|
|
||||||
|
if (canonical == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Erwartet: domain.containerName:ID=AGENT
|
||||||
|
if (!canonical.regionMatches(
|
||||||
|
true,
|
||||||
|
0,
|
||||||
|
domainPrefix,
|
||||||
|
0,
|
||||||
|
domainPrefix.length()))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int colon = canonical.indexOf(':');
|
||||||
|
|
||||||
|
if (colon <= domainPrefix.length())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String containerName =
|
||||||
|
canonical.substring(
|
||||||
|
domainPrefix.length(),
|
||||||
|
colon);
|
||||||
|
|
||||||
|
if (isBlank(containerName))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println(
|
||||||
|
"CONTAINER="
|
||||||
|
+ containerName.trim());
|
||||||
|
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println(
|
||||||
|
"OK:ContainerListEnd count="
|
||||||
|
+ count
|
||||||
|
+ " domain="
|
||||||
|
+ domain
|
||||||
|
+ " tool="
|
||||||
|
+ TOOL_VERSION);
|
||||||
|
|
||||||
|
System.out.flush();
|
||||||
|
}
|
||||||
|
|
||||||
private static Object connect(
|
private static Object connect(
|
||||||
String url,
|
String url,
|
||||||
String user,
|
String user,
|
||||||
@@ -126,17 +244,9 @@ public final class SonicMfConta*nerTool
|
|||||||
{
|
{
|
||||||
Hashtable environment = new Hashtable();
|
Hashtable environment = new Hashtable();
|
||||||
|
|
||||||
environment.put(
|
environment.put("ConnectionURLs", url);
|
||||||
"ConnectionURLs",
|
environment.put("DefaultUser", user);
|
||||||
url);
|
environment.put("DefaultPassword", password);
|
||||||
|
|
||||||
environment.put(
|
|
||||||
"DefaultUser",
|
|
||||||
user);
|
|
||||||
|
|
||||||
environment.put(
|
|
||||||
"DefaultPassword",
|
|
||||||
password);
|
|
||||||
|
|
||||||
Class addressClass = Class.forName(
|
Class addressClass = Class.forName(
|
||||||
"com.sonicsw.mf.jmx.client.JMSConnectorAddress");
|
"com.sonicsw.mf.jmx.client.JMSConnectorAddress");
|
||||||
@@ -160,18 +270,14 @@ public final class SonicMfConta*nerTool
|
|||||||
.getConstructor(new Class[] {})
|
.getConstructor(new Class[] {})
|
||||||
.newInstance(new Object[] {});
|
.newInstance(new Object[] {});
|
||||||
|
|
||||||
trySetTimeout(
|
trySetTimeout(connector, timeoutMilliseconds);
|
||||||
connector,
|
|
||||||
timeoutMilliseconds);
|
|
||||||
|
|
||||||
Method connectMethod =
|
Method connectMethod = findConnect(clientClass);
|
||||||
findConnect(clientClass);
|
|
||||||
|
|
||||||
if (connectMethod == null)
|
if (connectMethod == null)
|
||||||
{
|
{
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"JMSConnectorClient.connect(...) "
|
"JMSConnectorClient.connect(...) wurde nicht gefunden.");
|
||||||
+ "wurde nicht gefunden.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Class[] parameterTypes =
|
Class[] parameterTypes =
|
||||||
@@ -202,33 +308,18 @@ public final class SonicMfConta*nerTool
|
|||||||
return connector;
|
return connector;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Führt ausschließlich eine lesende Prüfung aus.
|
|
||||||
*
|
|
||||||
* Die erfolgreiche Verbindung bestätigt bereits die Anmeldung.
|
|
||||||
* Zusätzlich wird versucht, die MBean-Information des Containers
|
|
||||||
* zu lesen. Es wird keine stop-, start- oder restart-Operation
|
|
||||||
* aufgerufen.
|
|
||||||
*/
|
|
||||||
private static void validateConnection(
|
private static void validateConnection(
|
||||||
Object connector,
|
Object connector,
|
||||||
String domain,
|
String domain,
|
||||||
String container)
|
String container)
|
||||||
throws Exception
|
throws Exception
|
||||||
{
|
{
|
||||||
String shortName =
|
String shortName = shortContainer(container);
|
||||||
shortContainer(container);
|
|
||||||
|
|
||||||
ObjectName objectName =
|
ObjectName objectName = new ObjectName(
|
||||||
new ObjectName(
|
domain + "." + shortName + ":ID=AGENT");
|
||||||
domain
|
|
||||||
+ "."
|
|
||||||
+ shortName
|
|
||||||
+ ":ID=AGENT");
|
|
||||||
|
|
||||||
info(
|
info("ValidatingObjectName=" + objectName);
|
||||||
"ValidatingObjectName="
|
|
||||||
+ objectName);
|
|
||||||
|
|
||||||
Method getMBeanInfoMethod =
|
Method getMBeanInfoMethod =
|
||||||
findMethod(
|
findMethod(
|
||||||
@@ -242,9 +333,7 @@ public final class SonicMfConta*nerTool
|
|||||||
if (getMBeanInfoMethod == null)
|
if (getMBeanInfoMethod == null)
|
||||||
{
|
{
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"Die lesende MfApi-Methode "
|
"getMBeanInfo(ObjectName) wurde nicht gefunden.");
|
||||||
+ "getMBeanInfo(ObjectName) "
|
|
||||||
+ "wurde nicht gefunden.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Object result = getMBeanInfoMethod.invoke(
|
Object result = getMBeanInfoMethod.invoke(
|
||||||
@@ -278,61 +367,34 @@ public final class SonicMfConta*nerTool
|
|||||||
String container)
|
String container)
|
||||||
throws Exception
|
throws Exception
|
||||||
{
|
{
|
||||||
String shortName =
|
String shortName = shortContainer(container);
|
||||||
shortContainer(container);
|
|
||||||
|
|
||||||
ObjectName objectName =
|
ObjectName objectName = new ObjectName(
|
||||||
new ObjectName(
|
domain + "." + shortName + ":ID=AGENT");
|
||||||
domain
|
|
||||||
+ "."
|
|
||||||
+ shortName
|
|
||||||
+ ":ID=AGENT");
|
|
||||||
|
|
||||||
info(
|
info("ObjectName=" + objectName);
|
||||||
"ObjectName="
|
|
||||||
+ objectName);
|
|
||||||
|
|
||||||
StringBuffer attempts =
|
StringBuffer attempts = new StringBuffer();
|
||||||
new StringBuffer();
|
String[] operations = new String[]
|
||||||
|
|
||||||
String[] operations =
|
|
||||||
new String[]
|
|
||||||
{
|
|
||||||
"stop",
|
|
||||||
"restart"
|
|
||||||
};
|
|
||||||
|
|
||||||
for (int index = 0;
|
|
||||||
index < operations.length;
|
|
||||||
index++)
|
|
||||||
{
|
{
|
||||||
String operation =
|
"stop",
|
||||||
operations[index];
|
"restart"
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int index = 0; index < operations.length; index++)
|
||||||
|
{
|
||||||
|
String operation = operations[index];
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
info(
|
info("Trying MBean.invoke(" + operation + ")");
|
||||||
"Trying MBean.invoke("
|
invokeNoArgs(connector, objectName, operation);
|
||||||
+ operation
|
okRestart("MBean." + operation, shortName, domain);
|
||||||
+ ")");
|
|
||||||
|
|
||||||
invokeNoArgs(
|
|
||||||
connector,
|
|
||||||
objectName,
|
|
||||||
operation);
|
|
||||||
|
|
||||||
okRestart(
|
|
||||||
"MBean." + operation,
|
|
||||||
shortName,
|
|
||||||
domain);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
catch (Throwable throwable)
|
catch (Throwable throwable)
|
||||||
{
|
{
|
||||||
Throwable root =
|
Throwable root = rootOf(throwable);
|
||||||
rootOf(throwable);
|
|
||||||
|
|
||||||
String line =
|
String line =
|
||||||
"MBean."
|
"MBean."
|
||||||
+ operation
|
+ operation
|
||||||
@@ -342,30 +404,12 @@ public final class SonicMfConta*nerTool
|
|||||||
+ root.getMessage();
|
+ root.getMessage();
|
||||||
|
|
||||||
warn(line);
|
warn(line);
|
||||||
|
attempts.append(line).append('\n');
|
||||||
attempts
|
|
||||||
.append(line)
|
|
||||||
.append('\n');
|
|
||||||
|
|
||||||
if ("stop".equals(operation)
|
|
||||||
&& looksLikeStopSideEffect(root))
|
|
||||||
{
|
|
||||||
okRestart(
|
|
||||||
"MBean.stop(side-effect)",
|
|
||||||
shortName,
|
|
||||||
domain);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"Neustart fehlgeschlagen. "
|
"Neustart fehlgeschlagen:\n" + attempts.toString());
|
||||||
+ "ToolVersion="
|
|
||||||
+ TOOL_VERSION
|
|
||||||
+ "\nAttempts:\n"
|
|
||||||
+ attempts.toString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void invokeNoArgs(
|
private static void invokeNoArgs(
|
||||||
@@ -375,7 +419,8 @@ public final class SonicMfConta*nerTool
|
|||||||
throws Exception
|
throws Exception
|
||||||
{
|
{
|
||||||
Method invokeMethod =
|
Method invokeMethod =
|
||||||
connector.getClass().getMethod(
|
findMethod(
|
||||||
|
connector.getClass(),
|
||||||
"invoke",
|
"invoke",
|
||||||
new Class[]
|
new Class[]
|
||||||
{
|
{
|
||||||
@@ -385,86 +430,34 @@ public final class SonicMfConta*nerTool
|
|||||||
String[].class
|
String[].class
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (invokeMethod == null)
|
||||||
|
{
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"invoke(...) wurde nicht gefunden.");
|
||||||
|
}
|
||||||
|
|
||||||
invokeMethod.invoke(
|
invokeMethod.invoke(
|
||||||
connector,
|
connector,
|
||||||
new Object[]
|
new Object[]
|
||||||
{
|
{
|
||||||
objectName,
|
objectName,
|
||||||
operation,
|
operation,
|
||||||
new Object[0],
|
null,
|
||||||
new String[0]
|
null
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void disconnect(
|
|
||||||
Object connector)
|
|
||||||
{
|
|
||||||
if (connector == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
connector
|
|
||||||
.getClass()
|
|
||||||
.getMethod("disconnect")
|
|
||||||
.invoke(connector);
|
|
||||||
}
|
|
||||||
catch (Exception ignored)
|
|
||||||
{
|
|
||||||
// Die eigentliche Prüfung oder der Neustart
|
|
||||||
// darf durch einen Disconnect-Fehler nicht
|
|
||||||
// überschrieben werden.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Method findMethod(
|
|
||||||
Class targetClass,
|
|
||||||
String methodName,
|
|
||||||
Class[] parameterTypes)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return targetClass.getMethod(
|
|
||||||
methodName,
|
|
||||||
parameterTypes);
|
|
||||||
}
|
|
||||||
catch (Exception ignored)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean looksLikeStopSideEffect(
|
|
||||||
Throwable root)
|
|
||||||
{
|
|
||||||
if (root == null
|
|
||||||
|| root.getMessage() == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
String message =
|
|
||||||
root.getMessage().toLowerCase();
|
|
||||||
|
|
||||||
return message.indexOf("disconnect") >= 0
|
|
||||||
|| message.indexOf("closed") >= 0
|
|
||||||
|| message.indexOf("not connected") >= 0
|
|
||||||
|| message.indexOf("connection lost") >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void okRestart(
|
private static void okRestart(
|
||||||
String method,
|
String path,
|
||||||
String shortName,
|
String container,
|
||||||
String domain)
|
String domain)
|
||||||
{
|
{
|
||||||
System.out.println(
|
System.out.println(
|
||||||
"OK:RestartInvoked"
|
"OK:RestartInvoked"
|
||||||
+ " method="
|
+ " path="
|
||||||
+ method
|
+ path
|
||||||
+ " container="
|
+ " container="
|
||||||
+ shortName
|
+ container
|
||||||
+ " domain="
|
+ " domain="
|
||||||
+ domain
|
+ domain
|
||||||
+ " tool="
|
+ " tool="
|
||||||
@@ -473,43 +466,24 @@ public final class SonicMfConta*nerTool
|
|||||||
System.out.flush();
|
System.out.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Method findConnect(
|
private static void disconnect(Object connector)
|
||||||
Class clientClass)
|
|
||||||
{
|
{
|
||||||
Method[] methods =
|
try
|
||||||
clientClass.getMethods();
|
|
||||||
|
|
||||||
Method bestMethod = null;
|
|
||||||
|
|
||||||
for (int index = 0;
|
|
||||||
index < methods.length;
|
|
||||||
index++)
|
|
||||||
{
|
{
|
||||||
Method method =
|
Method method =
|
||||||
methods[index];
|
findMethod(
|
||||||
|
connector.getClass(),
|
||||||
|
"disconnect",
|
||||||
|
new Class[] {});
|
||||||
|
|
||||||
if (!"connect".equals(
|
if (method != null)
|
||||||
method.getName()))
|
|
||||||
{
|
{
|
||||||
continue;
|
method.invoke(connector, new Object[] {});
|
||||||
}
|
|
||||||
|
|
||||||
Class[] parameterTypes =
|
|
||||||
method.getParameterTypes();
|
|
||||||
|
|
||||||
if (parameterTypes.length == 1
|
|
||||||
|| parameterTypes.length == 2)
|
|
||||||
{
|
|
||||||
bestMethod = method;
|
|
||||||
|
|
||||||
if (parameterTypes.length == 2)
|
|
||||||
{
|
|
||||||
return method;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Throwable ignored)
|
||||||
return bestMethod;
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void trySetTimeout(
|
private static void trySetTimeout(
|
||||||
@@ -518,238 +492,197 @@ public final class SonicMfConta*nerTool
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
connector
|
Method method =
|
||||||
.getClass()
|
findMethod(
|
||||||
.getMethod(
|
connector.getClass(),
|
||||||
"setTimeout",
|
"setTimeout",
|
||||||
new Class[]
|
new Class[]
|
||||||
{
|
{
|
||||||
Long.TYPE
|
Long.TYPE
|
||||||
})
|
});
|
||||||
.invoke(
|
|
||||||
|
if (method != null)
|
||||||
|
{
|
||||||
|
method.invoke(
|
||||||
connector,
|
connector,
|
||||||
new Object[]
|
new Object[]
|
||||||
{
|
{
|
||||||
Long.valueOf(
|
Long.valueOf(timeoutMilliseconds)
|
||||||
timeoutMilliseconds)
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ignored)
|
catch (Throwable ignored)
|
||||||
{
|
{
|
||||||
try
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Method findConnect(Class clientClass)
|
||||||
|
{
|
||||||
|
Method[] methods = clientClass.getMethods();
|
||||||
|
|
||||||
|
for (int index = 0; index < methods.length; index++)
|
||||||
|
{
|
||||||
|
Method method = methods[index];
|
||||||
|
|
||||||
|
if (!"connect".equals(method.getName()))
|
||||||
{
|
{
|
||||||
connector
|
continue;
|
||||||
.getClass()
|
|
||||||
.getMethod(
|
|
||||||
"setRequestTimeout",
|
|
||||||
new Class[]
|
|
||||||
{
|
|
||||||
Long.TYPE
|
|
||||||
})
|
|
||||||
.invoke(
|
|
||||||
connector,
|
|
||||||
new Object[]
|
|
||||||
{
|
|
||||||
Long.valueOf(
|
|
||||||
timeoutMilliseconds)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
catch (Exception ignoredSecond)
|
|
||||||
|
Class[] types = method.getParameterTypes();
|
||||||
|
|
||||||
|
if (types.length == 1 || types.length == 2)
|
||||||
{
|
{
|
||||||
// Optional, nicht jede Sonic-Version
|
return method;
|
||||||
// besitzt diese Methode.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Method findMethod(
|
||||||
|
Class type,
|
||||||
|
String name,
|
||||||
|
Class[] parameterTypes)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return type.getMethod(name, parameterTypes);
|
||||||
|
}
|
||||||
|
catch (NoSuchMethodException exception)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object boxTimeout(
|
private static Object boxTimeout(
|
||||||
Class type,
|
Class parameterType,
|
||||||
long timeoutMilliseconds)
|
long timeoutMilliseconds)
|
||||||
{
|
{
|
||||||
if (type == Integer.TYPE
|
if (parameterType == Integer.TYPE
|
||||||
|| type == Integer.class)
|
|| parameterType == Integer.class)
|
||||||
{
|
{
|
||||||
return Integer.valueOf(
|
long seconds =
|
||||||
(int) Math.min(
|
Math.max(1L, timeoutMilliseconds / 1000L);
|
||||||
Integer.MAX_VALUE,
|
|
||||||
timeoutMilliseconds));
|
if (seconds > Integer.MAX_VALUE)
|
||||||
|
{
|
||||||
|
seconds = Integer.MAX_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Integer.valueOf((int) seconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Long.valueOf(
|
return Long.valueOf(timeoutMilliseconds);
|
||||||
timeoutMilliseconds);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String shortContainer(
|
private static String shortContainer(String container)
|
||||||
String container)
|
|
||||||
{
|
{
|
||||||
String value =
|
String value = container.trim();
|
||||||
container.trim();
|
int colon = value.indexOf(':');
|
||||||
|
|
||||||
int dotIndex =
|
if (colon > 0)
|
||||||
value.lastIndexOf('.');
|
{
|
||||||
|
value = value.substring(0, colon);
|
||||||
|
}
|
||||||
|
|
||||||
return dotIndex >= 0
|
int dot = value.lastIndexOf('.');
|
||||||
? value.substring(dotIndex + 1)
|
|
||||||
: value;
|
if (dot >= 0 && dot < value.length() - 1)
|
||||||
|
{
|
||||||
|
value = value.substring(dot + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Throwable rootOf(
|
private static Throwable rootOf(Throwable throwable)
|
||||||
Throwable throwable)
|
|
||||||
{
|
{
|
||||||
Throwable current =
|
Throwable current = throwable;
|
||||||
throwable;
|
|
||||||
|
|
||||||
while (current.getCause() != null
|
while (current.getCause() != null
|
||||||
&& current.getCause() != current)
|
&& current.getCause() != current)
|
||||||
{
|
{
|
||||||
current =
|
current = current.getCause();
|
||||||
current.getCause();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isBlank(
|
private static boolean isBlank(String value)
|
||||||
String value)
|
|
||||||
{
|
{
|
||||||
return value == null
|
return value == null || value.trim().length() == 0;
|
||||||
|| value.trim().length() == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void info(
|
private static void info(String message)
|
||||||
String message)
|
|
||||||
{
|
{
|
||||||
System.out.println(
|
System.err.println("INFO: " + message);
|
||||||
"INFO:" + message);
|
|
||||||
|
|
||||||
System.out.flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void warn(
|
private static void warn(String message)
|
||||||
String message)
|
|
||||||
{
|
{
|
||||||
System.out.println(
|
System.err.println("WARN: " + message);
|
||||||
"WARN:" + message);
|
|
||||||
|
|
||||||
System.out.flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void fail(
|
private static void fail(String message)
|
||||||
String message)
|
|
||||||
{
|
{
|
||||||
System.err.println(
|
System.err.println("ERROR: " + message);
|
||||||
"ERROR:" + message);
|
|
||||||
|
|
||||||
System.err.flush();
|
|
||||||
|
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class Args
|
private static final class Args
|
||||||
{
|
{
|
||||||
String command;
|
private String command;
|
||||||
String domain;
|
private String domain;
|
||||||
String url;
|
private String url;
|
||||||
String user;
|
private String user;
|
||||||
String password;
|
private String password;
|
||||||
String container;
|
private String container;
|
||||||
|
private int timeoutSec = 60;
|
||||||
|
|
||||||
int timeoutSec = 120;
|
private static Args parse(String[] args)
|
||||||
|
|
||||||
static Args parse(
|
|
||||||
String[] arguments)
|
|
||||||
{
|
{
|
||||||
Args parsedArguments =
|
Args result = new Args();
|
||||||
new Args();
|
|
||||||
|
|
||||||
if (arguments == null
|
if (args == null || args.length == 0)
|
||||||
|| arguments.length == 0)
|
|
||||||
{
|
{
|
||||||
return parsedArguments;
|
fail("Kein Befehl angegeben.");
|
||||||
}
|
}
|
||||||
|
|
||||||
parsedArguments.command =
|
result.command = args[0];
|
||||||
arguments[0];
|
result.password =
|
||||||
|
System.getenv("ESB_SONIC_PASSWORD");
|
||||||
|
|
||||||
for (int index = 1;
|
for (int index = 1; index < args.length; index++)
|
||||||
index < arguments.length;
|
|
||||||
index++)
|
|
||||||
{
|
{
|
||||||
String key =
|
String token = args[index];
|
||||||
arguments[index];
|
|
||||||
|
|
||||||
String value =
|
if ("--domain".equals(token) && index + 1 < args.length)
|
||||||
index + 1 < arguments.length
|
|
||||||
? arguments[index + 1]
|
|
||||||
: null;
|
|
||||||
|
|
||||||
if ("--domain".equals(key)
|
|
||||||
&& value != null)
|
|
||||||
{
|
{
|
||||||
parsedArguments.domain = value;
|
result.domain = args[++index];
|
||||||
index++;
|
|
||||||
}
|
}
|
||||||
else if ("--url".equals(key)
|
else if ("--url".equals(token) && index + 1 < args.length)
|
||||||
&& value != null)
|
|
||||||
{
|
{
|
||||||
parsedArguments.url = value;
|
result.url = args[++index];
|
||||||
index++;
|
|
||||||
}
|
}
|
||||||
else if ("--user".equals(key)
|
else if ("--user".equals(token) && index + 1 < args.length)
|
||||||
&& value != null)
|
|
||||||
{
|
{
|
||||||
parsedArguments.user = value;
|
result.user = args[++index];
|
||||||
index++;
|
|
||||||
}
|
}
|
||||||
else if ("--password".equals(key)
|
else if ("--container".equals(token)
|
||||||
&& value != null)
|
&& index + 1 < args.length)
|
||||||
{
|
{
|
||||||
parsedArguments.password = value;
|
result.container = args[++index];
|
||||||
index++;
|
|
||||||
}
|
}
|
||||||
else if ("--container".equals(key)
|
else if ("--timeout".equals(token)
|
||||||
&& value != null)
|
&& index + 1 < args.length)
|
||||||
{
|
{
|
||||||
parsedArguments.container = value;
|
result.timeoutSec =
|
||||||
index++;
|
Integer.parseInt(args[++index]);
|
||||||
}
|
|
||||||
else if ("--timeout".equals(key)
|
|
||||||
&& value != null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
parsedArguments.timeoutSec =
|
|
||||||
Integer.parseInt(value);
|
|
||||||
}
|
|
||||||
catch (Exception ignored)
|
|
||||||
{
|
|
||||||
// Standardwert beibehalten.
|
|
||||||
}
|
|
||||||
|
|
||||||
index++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isBlank(
|
return result;
|
||||||
parsedArguments.password))
|
|
||||||
{
|
|
||||||
String environmentPassword =
|
|
||||||
System.getenv(
|
|
||||||
"ESB_SONIC_PASSWORD");
|
|
||||||
|
|
||||||
if (!isBlank(
|
|
||||||
environmentPassword))
|
|
||||||
{
|
|
||||||
parsedArguments.password =
|
|
||||||
environmentPassword;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return parsedArguments;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private SonicMfContainerTool()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user