HTTP File Uploads with Sun’s Identity Manager 7.1

Identity Manager has a display class called FileUpload which you can use to do HTTP File Uploads. In a form, it would look something like this:

<Field name='fileUpload'>
    <Display class='FileUpload'>
        <Property name='Title' value='File to upload'/>
    </Display>
</Field>

In the above example, the field fileUpload would be set to an object of type DataSource. I want to use the contents of the file as a string in my XPRESS rules, but how do I do that?

The most obvious thing to try would be to invoke the appropriate java directly from XPRESS. Here is a rule that does that:

<Rule name="getStringFromFileUpload">
    <RuleArgument name='fileUpload'/>
 
    <block>
        <defvar name='bufferedReader'>
            <new class='java.io.BufferedReader'>
                <new class="java.io.InputStreamReader">
                    <invoke name='getInputStream'>
                        <ref>fileUpload</ref>
                    </invoke>
                </new>
            </new>
        </defvar>
         
        <defvar name='fileContentAsString'/>
         
        <defvar name='nextLine'>
            <invoke name='readLine'>
                <ref>bufferedReader</ref>
            </invoke>
        </defvar>
         
        <while>
            <notnull>
                <ref>nextLine</ref>
            </notnull>
            <block>
                <setvar name='fileContentAsString'>
                    <concat>
                        <ref>fileContentAsString</ref>
                        <ref>nextLine</ref>
                    </concat>
                </setvar>
                <setvar name='nextLine'>
                    <invoke name='readLine'>
                        <ref>bufferedReader</ref>
                    </invoke>
                </setvar>
            </block>
        </while>
        <ref>fileContentAsString</ref>
    </block>
</Rule>

Unfortunately, when I attempt that, I get this:

XPRESS exception ==> com.waveset.util.WavesetException: XPRESS exception ==> com.waveset.util.WavesetException: XPRESS exception ==> com.waveset.util.WavesetException: Couldn’t find method getInputStream() in class com.waveset.ui.util.BufferedRequest$AttachmentDataSource

That’s odd, because there really is a method called getInputStream on AttachmentDataSource. Ah well, so I seem to have hit a bug in XPRESS. No bother, I’ll just try invoking the appropriate Java in Javascript. Here is a rule that does that:

<Rule name="getStringFromFileUpload">
    <RuleArgument name='fileUpload'/>
 
    <script>
        importPackage(Packages.javax.activation);
        importPackage(Packages.com.waveset.ui.util);
        importPackage(Packages.java.io);
        importPackage(Packages.java.lang);
       
        var attachment = env.get('fileUpload');
       
        var fileContentsAsString = '';
       
        try {
       
            var bufferedReader = new BufferedReader(new InputStreamReader(attachment.getInputStream()));
       
            var line = '';
       
            while ((line = bufferedReader.readLine()) != null) {
                fileContentsAsString += line + "\n";
            }
        }
            catch(err) {
            result = err.getMessage();
        }
         
        fileContentsAsString;
    </script>
</Rule>

Hmm, no dice that way, either:

org.mozilla.javascript.EvaluatorException: Class org.mozilla.javascript.NativeJavaMethod can not access a member of class com.waveset.ui.util.BufferedRequest$AttachmentDataSource with modifiers “public”

OK, so it seems that it’s not just XPRESS, but Javascript also has a problem invoking the method. The only solution I could find is to write a custom bit of Java to do the actual work like this:

package net.woogie.idm.util;
 
import java.io.*;
import javax.activation.*;
import com.waveset.ui.util.*;
 
public class Attachment {
 
    public Attachment() {
    }
 
    public String toString(DataSource attachment) throws IOException {
 
        String fileContentsAsString = "";
 
        try {
            InputStream inputStream = attachment.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
 
            String line;
 
            while ((line = bufferedReader.readLine()) != null) {
                fileContentsAsString += line + "\n";
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
 
        return fileContentsAsString;
    }
}

And to invoke it via XPRESS like this:

<Rule name="getStringFromFileUpload">
    <RuleArgument name='fileUpload'/>
 
    <invoke name='toString'>
        <new class='net.woogie.idm.util.Attachment'/>
        <ref>fileUpload</ref>
    </invoke>
</Rule>

This works, but it sort of bums me out because it would be nice to have an XML only solution to this.