import java.lang.reflect.Method; import java.util.Hashtable; import javax.management.ObjectName; /** * Minimaler Sonic-Restart (wie SMC): JMSConnectorClient + MBean stop/restart. * Compile: javac --release 8 SonicMfContainerTool.java */ public final class SonicMfContainerTool { public static final String TOOL_VERSION = "2026-07-24d-restart-only"; public static void main(String[] args) { info("ToolVersion=" + TOOL_VERSION); try { Args a = Args.parse(args); if (!"restart".equals(a.command)) { fail("Usage: SonicMfContainerTool restart --domain D --url U --user U --container C [--timeout SEC]"); return; } if (isBlank(a.domain) || isBlank(a.url) || isBlank(a.user) || isBlank(a.container)) { fail("domain, url, user und container sind Pflicht."); return; } long timeoutMs = Math.max(5_000L, a.timeoutSec * 1000L); Object connector = connect(a.url, a.user, a.password, timeoutMs); try { restart(connector, a.domain, a.container); } finally { try { connector.getClass().getMethod("disconnect").invoke(connector); } catch (Exception ignore) { /* ignore */ } } } catch (Throwable t) { fail(rootOf(t).getClass().getName() + ": " + rootOf(t).getMessage()); } } private static Object connect(String url, String user, String password, long timeoutMs) throws Exception { Hashtable env = new Hashtable(); env.put("ConnectionURLs", url); env.put("DefaultUser", user); env.put("DefaultPassword", password == null ? "" : password); Class addressCl = Class.forName("com.sonicsw.mf.jmx.client.JMSConnectorAddress"); Object address = addressCl.getConstructor(new Class[] { Hashtable.class }).newInstance(new Object[] { env }); Class clientCl = Class.forName("com.sonicsw.mf.jmx.client.JMSConnectorClient"); Object connector = clientCl.getConstructor(new Class[] {}).newInstance(new Object[] {}); trySetTimeout(connector, timeoutMs); Method connect = findConnect(clientCl); if (connect == null) { fail("JMSConnectorClient.connect(...) nicht gefunden."); return null; } Class[] pts = connect.getParameterTypes(); if (pts.length == 2) { connect.invoke(connector, new Object[] { address, boxTimeout(pts[1], timeoutMs) }); } else { connect.invoke(connector, new Object[] { address }); } return connector; } private static void restart(Object connector, String domain, String container) throws Exception { String shortName = shortContainer(container); ObjectName on = new ObjectName(domain + "." + shortName + ":ID=AGENT"); info("ObjectName=" + on); StringBuffer attempts = new StringBuffer(); String[] ops = new String[] { "stop", "restart" }; for (int i = 0; i < ops.length; i++) { String op = ops[i]; try { info("Trying MBean.invoke(" + op + ")"); invokeNoArgs(connector, on, op); okRestart("MBean." + op, shortName, domain); return; } catch (Throwable t) { Throwable root = rootOf(t); String line = "MBean." + op + " => " + root.getClass().getName() + ": " + root.getMessage(); warn(line); attempts.append(line).append('\n'); if ("stop".equals(op) && looksLikeStopSideEffect(root)) { okRestart("MBean.stop(side-effect)", shortName, domain); return; } } } fail("Neustart fehlgeschlagen. ToolVersion=" + TOOL_VERSION + "\nAttempts:\n" + attempts.toString()); } private static void invokeNoArgs(Object connector, ObjectName on, String op) throws Exception { Method invoke = connector.getClass().getMethod("invoke", new Class[] { ObjectName.class, String.class, Object[].class, String[].class }); invoke.invoke(connector, new Object[] { on, op, new Object[0], new String[0] }); } private static boolean looksLikeStopSideEffect(Throwable root) { if (root == null || root.getMessage() == null) { return false; } String m = root.getMessage().toLowerCase(); return m.indexOf("disconnect") >= 0 || m.indexOf("closed") >= 0 || m.indexOf("not connected") >= 0 || m.indexOf("connection lost") >= 0; } private static void okRestart(String method, String shortName, String domain) { System.out.println("OK:RestartInvoked method=" + method + " container=" + shortName + " domain=" + domain + " tool=" + TOOL_VERSION); System.out.flush(); } private static Method findConnect(Class clientCl) { Method[] methods = clientCl.getMethods(); Method best = null; for (int i = 0; i < methods.length; i++) { Method m = methods[i]; if (!"connect".equals(m.getName())) { continue; } Class[] pts = m.getParameterTypes(); if (pts.length == 1 || pts.length == 2) { best = m; if (pts.length == 2) { return m; } } } return best; } private static void trySetTimeout(Object connector, long timeoutMs) { try { connector.getClass().getMethod("setTimeout", new Class[] { Long.TYPE }) .invoke(connector, new Object[] { Long.valueOf(timeoutMs) }); } catch (Exception ignore) { try { connector.getClass().getMethod("setRequestTimeout", new Class[] { Long.TYPE }) .invoke(connector, new Object[] { Long.valueOf(timeoutMs) }); } catch (Exception ignore2) { /* optional */ } } } private static Object boxTimeout(Class type, long timeoutMs) { if (type == Integer.TYPE || type == Integer.class) { return Integer.valueOf((int) Math.min(Integer.MAX_VALUE, timeoutMs)); } return Long.valueOf(timeoutMs); } private static String shortContainer(String container) { String c = container.trim(); int dot = c.lastIndexOf('.'); return dot >= 0 ? c.substring(dot + 1) : c; } private static Throwable rootOf(Throwable t) { Throwable cur = t; while (cur.getCause() != null && cur.getCause() != cur) { cur = cur.getCause(); } return cur; } private static boolean isBlank(String s) { return s == null || s.trim().length() == 0; } private static void info(String msg) { System.out.println("INFO:" + msg); System.out.flush(); } private static void warn(String msg) { System.out.println("WARN:" + msg); System.out.flush(); } private static void fail(String msg) { System.err.println("ERROR:" + msg); System.err.flush(); System.exit(1); } private static final class Args { String command; String domain; String url; String user; String password; String container; int timeoutSec = 120; static Args parse(String[] args) { Args a = new Args(); if (args == null || args.length == 0) { return a; } a.command = args[0]; for (int i = 1; i < args.length; i++) { String k = args[i]; String v = (i + 1 < args.length) ? args[i + 1] : null; if ("--domain".equals(k) && v != null) { a.domain = v; i++; } else if ("--url".equals(k) && v != null) { a.url = v; i++; } else if ("--user".equals(k) && v != null) { a.user = v; i++; } else if ("--password".equals(k) && v != null) { a.password = v; i++; } else if ("--container".equals(k) && v != null) { a.container = v; i++; } else if ("--timeout".equals(k) && v != null) { try { a.timeoutSec = Integer.parseInt(v); } catch (Exception ignore) { /* keep default */ } i++; } } if (isBlank(a.password)) { String env = System.getenv("ESB_SONIC_PASSWORD"); if (!isBlank(env)) { a.password = env; } } return a; } } private SonicMfContainerTool() { } }