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.