I’ve been doing a lot of work with Sun’s Identity Manager lately, and have some things that might be of interest to other’s so I’ll try to post them here as time permits.
I think the coolest thing I’ve done so far is to build a library for parsing XML within XPRESS. It’s actually fairly straightforward, but it took me long enough to get right that it seems like a good thing to share. I have 2 XPRESS rules:
- transformXML
- Takes 2 strings, xml and xsl, as input, and returns the transformed data.
- validateXML
- Takes 2 strings, xml and xsd, as input, and returns 1 true if the XML validates against the XSD, and returns false otherwise.
Both rules invoke Java to do the actual work, but for reasons I’ll explain later, validateXML is a bit more complex than transformXML. The XML transformation is simply a matter of figuring out the proper incantation to invoke:
<Rule name='transformXML'>
<RuleArgument name='xml'/>
<RuleArgument name='xsl'/>
<block>
<defvar name="StringWriter">
<new class="java.io.StringWriter"/>
</defvar>
<invoke name="transform">
<invoke name="newTransformer">
<invoke name="newInstance" class="javax.xml.transform.TransformerFactory"/>
<new class="javax.xml.transform.stream.StreamSource">
<new class="java.io.StringReader">
<ref>xsl</ref>
</new>
</new>
</invoke>
<new class="javax.xml.transform.stream.StreamSource">
<new class="java.io.StringReader">
<ref>xml</ref>
</new>
</new>
<new class="javax.xml.transform.stream.StreamResult">
<ref>StringWriter</ref>
</new>
</invoke>
<invoke name="toString">
<ref>StringWriter</ref>
</invoke>
</block>
</Rule>
That looks fairly complicated, but it is pretty much a straight translation from the Java to XPRESS invocations. Unfortunately, XML validation isn’t quite as straightforward. If there is a way to do it without exception handling, which is not available in XPRESS, I don’t know what that way is. So, the direct invocations similar to the code above will not work.
It would be possible to write a bit of simple Java code to wrap the exception handling in a nice set of return codes, deploy that code with the IDM deployment and then invoke that from XPRESS, but I was really hoping to avoid custom Java if possible. In this case, JavaScript comes to the rescue (man, I never thought I would say that):
<Rule name='validateXML'>
<RuleArgument name='xsd'/>
<RuleArgument name='xml'/>
<cond>
<and>
<notnull>
<ref>xsd</ref>
</notnull>
<notnull>
<ref>xml</ref>
</notnull>
</and>
<script>
importPackage(Packages.javax.xml.validation);
importPackage(Packages.java.io);
importPackage(Packages.javax.xml.transform.stream);
var xsd = env.get('xsd');
var xml = env.get('xml');
var schemaFactory = SchemaFactory.newInstance('http://www.w3.org/2001/XMLSchema');
var schema = schemaFactory.newSchema(new StreamSource(new StringReader(xsd)));
var validator = schema.newValidator();
var result = 'true';
try {
validator.validate(new StreamSource(new StringReader(xml)));
}
catch(err) {
result = 'false';
}
result;
</script>
<s>false</s>
</cond>
</Rule>
I’ve attached a rule library containing both these rules that you should be able to import and use in your project.
Have Fun.