-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
update GroovyXmlTransform to understand new first-level XML elements
WildFly added new elements to the set of possible first-level elements in the XML configuration files. This commit updates the Subtree class to understand them (which requires making a difference between host.xml and domain.xml, as host.xml is suddenly very similar to standalone.xml). Also, to maintain correct order of the XML elements, it is no longer sufficient to maintain a single list which blends all the possibilities, so the list was split into three separate lists -- for the "domain" root element, for "host" and for "server".
- Loading branch information
Showing
4 changed files
with
189 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -59,12 +59,12 @@ public static Subtree management() { | |
return new Subtree(StaticSubtreeLocator.MANAGEMENT, SubtreeCreator.MANAGEMENT); | ||
} | ||
|
||
// using default profile in domain | ||
// using default profile in domain.xml | ||
public static Subtree profile() { | ||
return new Subtree(ProfileSubtreeLocator.INSTANCE, SubtreeCreator.PROFILE); | ||
} | ||
|
||
// using default profile in domain | ||
// using default profile in domain.xml | ||
public static Subtree subsystem(String subsystemName) { | ||
// can't create subsystem, don't know the version | ||
return new Subtree(new SubsystemSubtreeLocator(subsystemName), null); | ||
|
@@ -74,7 +74,7 @@ public static Subtree interfaces() { | |
return new Subtree(StaticSubtreeLocator.INTERFACES, SubtreeCreator.INTERFACES); | ||
} | ||
|
||
// in domain, tries to guess a corect name based on the default profile | ||
// in domain.xml, tries to guess a corect name based on the default profile | ||
public static Subtree socketBindingGroup() { | ||
return new Subtree(SocketBindingGroupSubtreeLocator.INSTANCE, SubtreeCreator.SOCKET_BINDING_GROUP); | ||
} | ||
|
@@ -113,6 +113,37 @@ public static Subtree servers() { | |
|
||
// --- | ||
|
||
private enum Type { | ||
DOMAIN("domain.xml"), | ||
HOST("host.xml"), | ||
SERVER("standalone.xml"), | ||
; | ||
|
||
private final String description; | ||
|
||
Type(String description) { | ||
this.description = description; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return description; | ||
} | ||
|
||
public static Type of(GPathResult root) { | ||
String rootElement = root.name(); | ||
if ("domain".equals(rootElement)) { | ||
return Type.DOMAIN; | ||
} else if ("host".equals(rootElement)) { | ||
return Type.HOST; | ||
} else if ("server".equals(rootElement)) { | ||
return Type.SERVER; | ||
} else { | ||
throw new IllegalArgumentException("Unknown root node '" + rootElement + "'"); | ||
} | ||
} | ||
} | ||
|
||
private interface SubtreeLocator { | ||
GPathResult locate(GPathResult root, OfflineOptions options) throws Exception; | ||
|
||
|
@@ -125,33 +156,34 @@ public GPathResult locate(GPathResult root, OfflineOptions options) { | |
} | ||
|
||
private static final class StaticSubtreeLocator implements SubtreeLocator { | ||
static final SubtreeLocator EXTENSIONS = new StaticSubtreeLocator("extensions", false); | ||
static final SubtreeLocator SYSTEM_PROPERTIES = new StaticSubtreeLocator("system-properties", false); | ||
static final SubtreeLocator PATHS = new StaticSubtreeLocator("paths", false); | ||
static final SubtreeLocator MANAGEMENT = new StaticSubtreeLocator("management", false); | ||
static final SubtreeLocator INTERFACES = new StaticSubtreeLocator("interfaces", false); | ||
|
||
static final SubtreeLocator PROFILES = new StaticSubtreeLocator("profiles", true); | ||
static final SubtreeLocator SOCKET_BINDING_GROUPS = new StaticSubtreeLocator("socket-binding-groups", true); | ||
static final SubtreeLocator SERVER_GROUPS = new StaticSubtreeLocator("server-groups", true); | ||
static final SubtreeLocator DOMAIN_CONTROLLER = new StaticSubtreeLocator("domain-controller", true); | ||
static final SubtreeLocator JVMS = new StaticSubtreeLocator("jvms", true); | ||
static final SubtreeLocator SERVERS = new StaticSubtreeLocator("servers", true); | ||
static final SubtreeLocator EXTENSIONS = new StaticSubtreeLocator("extensions", null); | ||
static final SubtreeLocator SYSTEM_PROPERTIES = new StaticSubtreeLocator("system-properties", null); | ||
static final SubtreeLocator PATHS = new StaticSubtreeLocator("paths", null); | ||
static final SubtreeLocator MANAGEMENT = new StaticSubtreeLocator("management", null); | ||
static final SubtreeLocator INTERFACES = new StaticSubtreeLocator("interfaces", null); | ||
|
||
static final SubtreeLocator PROFILES = new StaticSubtreeLocator("profiles", Type.DOMAIN); | ||
static final SubtreeLocator SOCKET_BINDING_GROUPS = new StaticSubtreeLocator("socket-binding-groups", | ||
Type.DOMAIN); | ||
static final SubtreeLocator SERVER_GROUPS = new StaticSubtreeLocator("server-groups", Type.DOMAIN); | ||
static final SubtreeLocator DOMAIN_CONTROLLER = new StaticSubtreeLocator("domain-controller", Type.HOST); | ||
static final SubtreeLocator JVMS = new StaticSubtreeLocator("jvms", Type.HOST); | ||
static final SubtreeLocator SERVERS = new StaticSubtreeLocator("servers", Type.HOST); | ||
|
||
private final String tagName; // only for a possible exception message | ||
private final Class scriptClass; | ||
private final boolean domainOnly; | ||
private final Type onlyForType; | ||
|
||
StaticSubtreeLocator(String tagName, boolean domainOnly) { | ||
StaticSubtreeLocator(String tagName, Type onlyForType) { | ||
String script = "root.\"" + tagName + "\""; | ||
this.tagName = tagName; | ||
this.scriptClass = (GroovyHolder.GROOVY.parseClass(script)); | ||
this.domainOnly = domainOnly; | ||
this.scriptClass = GroovyHolder.GROOVY.parseClass(script); | ||
this.onlyForType = onlyForType; | ||
} | ||
|
||
public GPathResult locate(GPathResult root, OfflineOptions options) throws Exception { | ||
if (domainOnly && !options.isDomain) { | ||
throw new IllegalArgumentException("Locating '" + tagName + "' is only possible in domain"); | ||
if (onlyForType != null && onlyForType != Type.of(root)) { | ||
throw new IllegalArgumentException("Locating '" + tagName + "' is only possible in '" + onlyForType + "'"); | ||
} | ||
Script script = (Script) scriptClass.newInstance(); | ||
script.setProperty("root", root); | ||
|
@@ -162,24 +194,26 @@ public GPathResult locate(GPathResult root, OfflineOptions options) throws Excep | |
private static final class ProfileSubtreeLocator implements SubtreeLocator { | ||
static final SubtreeLocator INSTANCE = new ProfileSubtreeLocator(); | ||
|
||
private static final Class STANDALONE_SCRIPT_CLASS = GroovyHolder.GROOVY.parseClass("root.profile"); | ||
private static final Class STANDALONE_OR_HOST_SCRIPT_CLASS = GroovyHolder.GROOVY.parseClass("root.profile"); | ||
private static final Class DOMAIN_SCRIPT_CLASS = GroovyHolder.GROOVY.parseClass("root.profiles.profile.find { it.@name == defaultProfile }"); | ||
|
||
@Override | ||
public GPathResult locate(GPathResult root, OfflineOptions options) throws Exception { | ||
boolean domain = Type.of(root) == Type.DOMAIN; | ||
|
||
Script script = (Script) ( | ||
options.isDomain ? DOMAIN_SCRIPT_CLASS.newInstance() : STANDALONE_SCRIPT_CLASS.newInstance() | ||
domain ? DOMAIN_SCRIPT_CLASS.newInstance() : STANDALONE_OR_HOST_SCRIPT_CLASS.newInstance() | ||
); | ||
script.setProperty("root", root); | ||
if (options.isDomain) { | ||
if (domain) { | ||
script.setProperty("defaultProfile", options.defaultProfile); | ||
} | ||
return (GPathResult) script.run(); | ||
} | ||
} | ||
|
||
private static final class SubsystemSubtreeLocator implements SubtreeLocator { | ||
private static final Class STANDALONE_SCRIPT_CLASS = GroovyHolder.GROOVY.parseClass("root.profile.subsystem.find { [email protected]().startsWith(\"urn:jboss:domain:${subsystemName}:\") }"); | ||
private static final Class STANDALONE_OR_HOST_SCRIPT_CLASS = GroovyHolder.GROOVY.parseClass("root.profile.subsystem.find { [email protected]().startsWith(\"urn:jboss:domain:${subsystemName}:\") }"); | ||
private static final Class DOMAIN_SCRIPT_CLASS = GroovyHolder.GROOVY.parseClass("root.profiles.profile.find { it.@name == defaultProfile }.subsystem.find { [email protected]().startsWith(\"urn:jboss:domain:${subsystemName}:\") }"); | ||
|
||
private final String subsystemName; | ||
|
@@ -190,12 +224,14 @@ public SubsystemSubtreeLocator(String subsystemName) { | |
|
||
@Override | ||
public GPathResult locate(GPathResult root, OfflineOptions options) throws Exception { | ||
boolean domain = Type.of(root) == Type.DOMAIN; | ||
|
||
Script script = (Script) ( | ||
options.isDomain ? DOMAIN_SCRIPT_CLASS.newInstance() : STANDALONE_SCRIPT_CLASS.newInstance() | ||
domain ? DOMAIN_SCRIPT_CLASS.newInstance() : STANDALONE_OR_HOST_SCRIPT_CLASS.newInstance() | ||
); | ||
script.setProperty("root", root); | ||
script.setProperty("subsystemName", subsystemName); | ||
if (options.isDomain) { | ||
if (domain) { | ||
script.setProperty("defaultProfile", options.defaultProfile); | ||
} | ||
return (GPathResult) script.run(); | ||
|
@@ -205,16 +241,18 @@ public GPathResult locate(GPathResult root, OfflineOptions options) throws Excep | |
private static final class SocketBindingGroupSubtreeLocator implements SubtreeLocator { | ||
static final SubtreeLocator INSTANCE = new SocketBindingGroupSubtreeLocator(); | ||
|
||
private static final Class STANDALONE_SCRIPT_CLASS = GroovyHolder.GROOVY.parseClass("root.\"socket-binding-group\""); | ||
private static final Class STANDALONE_OR_HOST_SCRIPT_CLASS = GroovyHolder.GROOVY.parseClass("root.\"socket-binding-group\""); | ||
private static final Class DOMAIN_SCRIPT_CLASS = GroovyHolder.GROOVY.parseClass("root.\"socket-binding-groups\".\"socket-binding-group\".find { it.@name == \"${defaultSocketBindingGroup}\" }"); | ||
|
||
@Override | ||
public GPathResult locate(GPathResult root, OfflineOptions options) throws Exception { | ||
boolean domain = Type.of(root) == Type.DOMAIN; | ||
|
||
Script script = (Script) ( | ||
options.isDomain ? DOMAIN_SCRIPT_CLASS.newInstance() : STANDALONE_SCRIPT_CLASS.newInstance() | ||
domain ? DOMAIN_SCRIPT_CLASS.newInstance() : STANDALONE_OR_HOST_SCRIPT_CLASS.newInstance() | ||
); | ||
script.setProperty("root", root); | ||
if (options.isDomain) { | ||
if (domain) { | ||
String defaultSocketBindingGroup = options.defaultProfile + "-sockets"; | ||
if ("default".equals(options.defaultProfile)) { | ||
defaultSocketBindingGroup = "standard-sockets"; | ||
|
@@ -285,7 +323,9 @@ private SubtreeCreator(String tagName, boolean skipInDomain) { | |
} | ||
|
||
void addIfMissing(GPathResult root, OfflineOptions options) { | ||
if (skipInDomain && options.isDomain) { | ||
boolean domain = Type.of(root) == Type.DOMAIN; | ||
|
||
if (skipInDomain && domain) { | ||
return; | ||
} | ||
|
||
|
73 changes: 73 additions & 0 deletions
73
...wildfly/extras/creaper/commands/foundation/offline/xml/FirstLevelXmlElementOrderTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package org.wildfly.extras.creaper.commands.foundation.offline.xml; | ||
|
||
import org.custommonkey.xmlunit.XMLUnit; | ||
import org.junit.BeforeClass; | ||
import org.junit.Test; | ||
import org.xml.sax.SAXException; | ||
|
||
import java.io.IOException; | ||
|
||
import static org.wildfly.extras.creaper.XmlAssert.assertXmlIdentical; | ||
|
||
public class FirstLevelXmlElementOrderTest { | ||
private static final String DOMAIN_XML = "" | ||
+ "<?xml version=\"1.0\" ?>\n" | ||
+ "<domain xmlns=\"urn:jboss:domain:4.1\">\n" | ||
+ " <extensions/>\n" | ||
+ " <system-properties/>\n" | ||
+ " <management/>\n" | ||
+ " <profiles/>\n" | ||
+ " <interfaces/>\n" | ||
+ " <socket-binding-groups/>\n" | ||
+ " <server-groups/>\n" | ||
+ "</domain>"; | ||
|
||
private static final String HOST_XML = "" | ||
+ "<?xml version=\"1.0\" ?>\n" | ||
+ "<host xmlns=\"urn:jboss:domain:4.1\" name=\"master\">\n" | ||
+ " <extensions/>\n" | ||
+ " <management/>\n" | ||
+ " <domain-controller/>\n" | ||
+ " <interfaces/>\n" | ||
+ " <jvms/>\n" | ||
+ " <servers/>\n" | ||
+ " <profile/>\n" | ||
+ "</host>"; | ||
|
||
private static final String SERVER_XML = "" | ||
+ "<?xml version=\"1.0\"?>\n" | ||
+ "<server xmlns=\"urn:jboss:domain:4.1\">\n" | ||
+ " <extensions/>\n" | ||
+ " <management/>\n" | ||
+ " <profile/>\n" | ||
+ " <interfaces/>\n" | ||
+ " <socket-binding-group/>\n" | ||
+ "</server>"; | ||
|
||
private static final String UNKNOWN_XML = "<foobar/>"; | ||
|
||
@BeforeClass | ||
public static void setUpXmlUnit() { | ||
XMLUnit.setIgnoreWhitespace(true); | ||
} | ||
|
||
@Test | ||
public void domain() throws IOException, SAXException { | ||
assertXmlIdentical(DOMAIN_XML, FirstLevelXmlElementOrder.fix(DOMAIN_XML)); | ||
} | ||
|
||
@Test | ||
public void host() throws IOException, SAXException { | ||
assertXmlIdentical(HOST_XML, FirstLevelXmlElementOrder.fix(HOST_XML)); | ||
} | ||
|
||
@Test | ||
public void server() throws IOException, SAXException { | ||
assertXmlIdentical(SERVER_XML, FirstLevelXmlElementOrder.fix(SERVER_XML)); | ||
} | ||
|
||
@Test(expected = IllegalArgumentException.class) | ||
public void unknown() { | ||
FirstLevelXmlElementOrder.fix(UNKNOWN_XML); | ||
} | ||
} |