Good Day,
I got the source from common/jbossxb and that seems to have the change to fix the attributes.
The problem is that when I add a handler for an element text then that xml node is duplicated, once without the text element and once with.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE policy PUBLIC "-//JBoss//DTD JBOSS Security Config 3.0//EN" "http://www.jboss.org/j2ee/dtd/security_config.dtd">
<policy>
<application-policy name="other">
<authentication>
<login-module flag="required" code="org.jboss.security.auth.spi.LdapExtLoginModule">
<module-option name="bindCredentials"></module-option>
<module-option name="java.naming.provider.url"></module-option>
</login-module>
</authentication>
</application-policy>
<application-policy name="test">
<authentication>
<login-module flag="required" code="org.jboss.security.auth.spi.LdapExtLoginModule">
<module-option name="bindCredentials"></module-option>
<module-option name="java.naming.provider.url"></module-option>
</login-module>
</authentication>
</application-policy>
</policy>
I have written a testcase to help with the fixing of the issue. The testcase has a dependancy on jbosssx.jar.
Here is my ObjectModelProvider
package org.jboss.xb.test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag;
import org.jboss.security.auth.login.AuthenticationInfo;
import org.jboss.security.auth.login.PolicyConfig;
import org.jboss.xb.binding.MarshallingContext;
import org.jboss.xb.binding.ObjectModelProvider;
/**
* @author Mark Ashworth
* @version 1.0.0
*/
public class LoginConfigObjectModelProvider implements ObjectModelProvider {
/**
* Used to simulate the authentication node
*/
static class Authentication {
public List<AppConfigurationEntry> entries;
public Authentication(List<AppConfigurationEntry> entries) {
this.entries = entries;
}
}
/**
* ROOT: policy
*/
public Object getRoot(
Object o,
MarshallingContext ctx,
String namespaceURI,
String localName) {
return o;
}
/**
* application-policy
*/
public Object getChildren(
PolicyConfig policyConfig,
String namespaceUri,
String localName) {
List<AuthenticationInfo> infos = new ArrayList<AuthenticationInfo>();
Set<String> keys = policyConfig.getConfigNames();
for (String name : keys) {
infos.add(policyConfig.get(name));
}
return infos;
}
/**
* application-policy name
*/
public Object getAttributeValue(
AuthenticationInfo authInfo,
String namespaceUri,
String localName) {
Object value = null;
if ("name".equals(localName)) {
value = authInfo.getName();
}
return value;
}
/**
* authentication
*/
public Object getChildren(
AuthenticationInfo authInfo,
String namespaceUri,
String localName) {
return new Authentication(Arrays.asList((authInfo.getAppConfigurationEntry())));
}
/**
* login-module
*/
public Object getChildren(
Authentication authentication,
String namespaceUri,
String localName) {
return authentication.entries;
}
/**
* login-module code flag
*/
public Object getAttributeValue(
AppConfigurationEntry entry,
String namespaceUri,
String localName) {
Object value = null;
if ("code".equals(localName)) {
value = entry.getLoginModuleName();
} else if ("flag".equals(localName)) {
if (entry.getControlFlag() == LoginModuleControlFlag.OPTIONAL) {
value = "optional";
} else if (entry.getControlFlag() == LoginModuleControlFlag.REQUIRED) {
value = "required";
} else if (entry.getControlFlag() == LoginModuleControlFlag.REQUISITE) {
value = "requisite";
} else if (entry.getControlFlag() == LoginModuleControlFlag.SUFFICIENT) {
value = "sufficient";
} else{
value = "";
}
}
return value;
}
/**
* module-option
*/
public Object getChildren(
AppConfigurationEntry entry,
String namespaceUri,
String localName) {
Map<String, ModuleOption> options = new HashMap<String, ModuleOption>();
Set<String> keys = entry.getOptions().keySet();
for (String key : keys) {
Object value = entry.getOptions().get(key);
options.put(key, new ModuleOption(key, value));
}
return options.values();
}
/**
* module-option name
*/
public Object getAttributeValue(
ModuleOption moduleOption,
String namespaceUri,
String localName) {
Object value = null;
if ("name".equals(localName)) {
value = moduleOption.getName();
}
return value;
}
/**
* module-option text
*/
// public Object getElementValue(
// ModuleOption moduleOption,
// String namespaceUri,
// String localName) {
//
// return moduleOption.getValue();
// }
}
package org.jboss.xb.test;
import java.io.Serializable;
/**
* @author Mark Ashworth
* @version 1.0.0
*/
public class ModuleOption implements Serializable {
/** Serial version id*/
private static final long serialVersionUID = 2105836972498754806L;
private String name;
private Object value = "";
/**
* Constructs an option with a null value
* @param name The name of the option
*/
public ModuleOption(String name) {
this.name = name;
}
/**
* Constructs an option with a null value
* @param name The name of the option
* @param value The value of the option
*/
public ModuleOption(String name, Object value) {
this.name = name;
this.value = value;
}
/**
* Returns the option name
* @return The name of the option
*/
public String getName() {
return name;
}
/**
* Returns the option value
* @return The value of the option
*/
public Object getValue() {
return value;
}
/**
* Sets the option value
* @param value The value of the option
*/
public void setValue(Object value) {
this.value = value;
}
/**
* Returns whether the option is a password / credential
* @return boolean
*/
public boolean isPassword() {
if (getName() == null) {
return false;
}
String value = getName().toUpperCase();
if (value.indexOf("PASSWORD") >= 0) {
return true;
}
if (value.indexOf("PWD") >= 0) {
return true;
}
if (value.indexOf("CREDENTIAL") >= 0) {
return true;
}
return false;
}
}
package org.jboss.xb.test;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag;
import junit.framework.TestCase;
import org.jboss.security.auth.login.AuthenticationInfo;
import org.jboss.security.auth.login.PolicyConfig;
import org.jboss.security.auth.spi.LdapExtLoginModule;
import org.jboss.xb.binding.AbstractMarshaller;
import org.jboss.xb.binding.DtdMarshaller;
import org.jboss.xb.binding.Marshaller;
public class TestPolicyConfigMarshalling extends TestCase {
public void testMarshal() throws Exception {
/*
* Create the PolicyConfig Object
*/
Map<String, Object> options = new HashMap<String, Object>();
options.put("bindCredentials", "password");
options.put("java.naming.provider.url", "ldap://localhost:389");
AuthenticationInfo[] authInfos = new AuthenticationInfo[2];
authInfos[0] = new AuthenticationInfo("other");
authInfos[0].addAppConfigurationEntry(
new AppConfigurationEntry(LdapExtLoginModule.class.getName(),
LoginModuleControlFlag.REQUIRED, options));
authInfos[1] = new AuthenticationInfo("test");
authInfos[1].addAppConfigurationEntry(
new AppConfigurationEntry(LdapExtLoginModule.class.getName(),
LoginModuleControlFlag.REQUIRED, options));
PolicyConfig config = new PolicyConfig();
config.add(authInfos[0]);
config.add(authInfos[1]);
/*
* Marshal the PolicyConfig to XML using the DTD
*/
StringWriter xmlOutput = new StringWriter();
System.setProperty(Marshaller.PROP_MARSHALLER, DtdMarshaller.class
.getName());
AbstractMarshaller marshaller = (AbstractMarshaller) Marshaller.FACTORY
.getInstance();
marshaller.mapPublicIdToSystemId(
"-//JBoss//DTD JBOSS Security Config 3.0//EN",
"http://www.jboss.org/j2ee/dtd/security_config.dtd");
LoginConfigObjectModelProvider provider = new LoginConfigObjectModelProvider();
marshaller.marshal("http://www.jboss.org/j2ee/dtd/security_config.dtd",
provider, config, xmlOutput);
System.out.println(xmlOutput.getBuffer());
}
}
I could probably attach the files to the Jira task once it is created.
Regards,
Mark P Ashworth