import java.lang.reflect.Method; import java.util.Hashtable; import javax.management.ObjectName; /** * Sonic-MfApi-Hilfsprogramm. * * Befehle: * validate - Anmeldung + lesender Container-Zugriff * restart - Container neu starten (stop/restart) * * javac -source 8 -target 8 SonicMfContainerTool.java */ public final class SonicMfContainerTool { public static final String TOOL_VERSION = "2026-07-29-restart-empty-params"; public static void main(String[] args) { info("ToolVersion=" + TOOL_VERSION); try { Args parsedArguments = Args.parse(args); if (!"validate".equals(parsedArguments.command) && !"restart".equals(parsedArguments.command)) { fail( "Usage: SonicMfContainerTool " + " " + "--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; } if (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; } long timeoutMilliseconds = Math.max( 5_000L, parsedArguments.timeoutSec * 1000L); Object connector = connect( parsedArguments.url, parsedArguments.user, parsedArguments.password, timeoutMilliseconds); try { if ("validate".equals( parsedArguments.command)) { validateConnection( connector, parsedArguments.domain, parsedArguments.container); } else { restart( connector, parsedArguments.domain, parsedArguments.container); } } finally { disconnect(connector); } } catch (Throwable throwable) { Throwable root = rootOf(throwable); String message = root.getMessage(); if (message == null) { message = "(keine Detailmeldung)"; } fail( root.getClass().getName() + ": " + message); } } private static Object connect( String url, String user, String password, long timeoutMilliseconds) throws Exception { Hashtable environment = new Hashtable(); environment.put("ConnectionURLs", url); environment.put("DefaultUser", user); environment.put("DefaultPassword", password); Class addressClass = Class.forName( "com.sonicsw.mf.jmx.client.JMSConnectorAddress"); Object address = addressClass .getConstructor( new Class[] { Hashtable.class }) .newInstance( new Object[] { environment }); Class clientClass = Class.forName( "com.sonicsw.mf.jmx.client.JMSConnectorClient"); Object connector = clientClass .getConstructor(new Class[] {}) .newInstance(new Object[] {}); trySetTimeout(connector, timeoutMilliseconds); Method connectMethod = findConnect(clientClass); if (connectMethod == null) { throw new IllegalStateException( "JMSConnectorClient.connect(...) wurde nicht gefunden."); } Class[] parameterTypes = connectMethod.getParameterTypes(); if (parameterTypes.length == 2) { connectMethod.invoke( connector, new Object[] { address, boxTimeout( parameterTypes[1], timeoutMilliseconds) }); } else { connectMethod.invoke( connector, new Object[] { address }); } return connector; } private static void validateConnection( Object connector, String domain, String container) throws Exception { String shortName = shortContainer(container); ObjectName objectName = new ObjectName( domain + "." + shortName + ":ID=AGENT"); info("ValidatingObjectName=" + objectName); Method getMBeanInfoMethod = findMethod( connector.getClass(), "getMBeanInfo", new Class[] { ObjectName.class }); if (getMBeanInfoMethod == null) { throw new IllegalStateException( "getMBeanInfo(ObjectName) wurde nicht gefunden."); } Object result = getMBeanInfoMethod.invoke( connector, new Object[] { objectName }); if (result == null) { throw new IllegalStateException( "Die Container-MBean konnte nicht gelesen werden."); } System.out.println( "OK:ConnectionValidated" + " container=" + shortName + " domain=" + domain + " tool=" + TOOL_VERSION); System.out.flush(); } private static void restart( Object connector, String domain, String container) throws Exception { String shortName = shortContainer(container); ObjectName objectName = new ObjectName( domain + "." + shortName + ":ID=AGENT"); info("ObjectName=" + objectName); StringBuffer attempts = new StringBuffer(); // 1) restart (bevorzugt) // 2) stop + start (Fallback; manche Agenten haben kein restart) String[][] plans = new String[][] { { "restart" }, { "stop", "start" } }; for (int planIndex = 0; planIndex < plans.length; planIndex++) { String[] operations = plans[planIndex]; try { for (int index = 0; index < operations.length; index++) { String operation = operations[index]; info("Trying MBean.invoke(" + operation + ")"); invokeNoArgs(connector, objectName, operation); } okRestart( "MBean." + joinOps(operations), shortName, domain); return; } catch (Throwable throwable) { Throwable root = rootOf(throwable); String line = "MBean." + joinOps(operations) + " => " + root.getClass().getName() + ": " + root.getMessage(); warn(line); attempts.append(line).append('\n'); } } throw new IllegalStateException( "Neustart fehlgeschlagen:\n" + attempts.toString()); } private static String joinOps(String[] operations) { StringBuffer buffer = new StringBuffer(); for (int index = 0; index < operations.length; index++) { if (index > 0) { buffer.append('+'); } buffer.append(operations[index]); } return buffer.toString(); } private static void invokeNoArgs( Object connector, ObjectName objectName, String operation) throws Exception { Method invokeMethod = findMethod( connector.getClass(), "invoke", new Class[] { ObjectName.class, String.class, Object[].class, String[].class }); if (invokeMethod == null) { throw new IllegalStateException( "invoke(...) wurde nicht gefunden."); } // Sonic JMSConnectorClient verlangt leere Arrays, nicht null. Object[] params = new Object[0]; String[] signature = new String[0]; invokeMethod.invoke( connector, new Object[] { objectName, operation, params, signature }); } private static void okRestart( String path, String container, String domain) { System.out.println( "OK:RestartInvoked" + " path=" + path + " container=" + container + " domain=" + domain + " tool=" + TOOL_VERSION); System.out.flush(); } private static void disconnect(Object connector) { try { Method method = findMethod( connector.getClass(), "disconnect", new Class[] {}); if (method != null) { method.invoke(connector, new Object[] {}); } } catch (Throwable ignored) { } } private static void trySetTimeout( Object connector, long timeoutMilliseconds) { try { Method method = findMethod( connector.getClass(), "setTimeout", new Class[] { Long.TYPE }); if (method != null) { method.invoke( connector, new Object[] { Long.valueOf(timeoutMilliseconds) }); } } catch (Throwable ignored) { } } 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())) { continue; } Class[] types = method.getParameterTypes(); if (types.length == 1 || types.length == 2) { return method; } } 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( Class parameterType, long timeoutMilliseconds) { if (parameterType == Integer.TYPE || parameterType == Integer.class) { long seconds = Math.max(1L, timeoutMilliseconds / 1000L); if (seconds > Integer.MAX_VALUE) { seconds = Integer.MAX_VALUE; } return Integer.valueOf((int) seconds); } return Long.valueOf(timeoutMilliseconds); } private static String shortContainer(String container) { String value = container.trim(); int colon = value.indexOf(':'); if (colon > 0) { value = value.substring(0, colon); } int dot = value.lastIndexOf('.'); if (dot >= 0 && dot < value.length() - 1) { value = value.substring(dot + 1); } return value; } private static Throwable rootOf(Throwable throwable) { Throwable current = throwable; while (current.getCause() != null && current.getCause() != current) { current = current.getCause(); } return current; } private static boolean isBlank(String value) { return value == null || value.trim().length() == 0; } private static void info(String message) { System.err.println("INFO: " + message); } private static void warn(String message) { System.err.println("WARN: " + message); } private static void fail(String message) { System.err.println("ERROR: " + message); System.exit(1); } private static final class Args { private String command; private String domain; private String url; private String user; private String password; private String container; private int timeoutSec = 60; private static Args parse(String[] args) { Args result = new Args(); if (args == null || args.length == 0) { fail("Kein Befehl angegeben."); } result.command = args[0]; result.password = System.getenv("ESB_SONIC_PASSWORD"); for (int index = 1; index < args.length; index++) { String token = args[index]; if ("--domain".equals(token) && index + 1 < args.length) { result.domain = args[++index]; } else if ("--url".equals(token) && index + 1 < args.length) { result.url = args[++index]; } else if ("--user".equals(token) && index + 1 < args.length) { result.user = args[++index]; } else if ("--container".equals(token) && index + 1 < args.length) { result.container = args[++index]; } else if ("--timeout".equals(token) && index + 1 < args.length) { result.timeoutSec = Integer.parseInt(args[++index]); } } return result; } } }