Discussions
Categories
Groups
Community Home
Categories
INTERNAL ENABLEMENT
POPULAR
PUBLIC CLOUD
PRIVATE CLOUD
Quick Links
MY LINKS
HELPFUL TIPS
Back to website
Home
Intelligence (Analytics)
IResourceLocator inconveniency
Tomas.Vala
Hi,<br />
<br />
there are situations where <strong class='bbc'>IResourceLocator</strong> is unneccessarily inconvenient to use. <br />
<br />
Unlike for instance IReportEngine.openReportDesign() which accepts argument of type <strong class='bbc'>InputStream</strong> (lovely), IResourceLocator only allows refering to resources, even resources of type RPT Library which is basically same as RPT Design, exclusively through <strong class='bbc'>URL</strong>.<br />
<br />
This becomes obvious complication if your resource provider tier uses streams to deliver requested data. Extra steps involving data persistence to filesystem and cleanup is what bothers me.<br />
<br />
Please consider this as a suggestion for future enhancement.<br />
<br />
Tomas
Find more posts tagged with
Comments
JasonW
Tomas,
Can you open a bugzilla entry for this?
Jason
Tomas.Vala
Hi Jason,
yes I can.
Tomas
zimmi
Hi Thomas and Jason,<br />
<br />
it might be a little late, but I'd like to post my solution to this problem for others that may find this thread (like I did).<br />
<br />
It is possible to use an IResourceLocator for in-memory InputStreams without compromising backward compatibility of the IResourceLocator interface.<br />
The API to deal with URLs may be a little bit clunky, but it provides a mechanic to directly return an InputStream for a given URL: URLStreamHandlers.<br />
<br />
Example code:<br />
<br />
<pre class='_prettyXprint _lang-auto _linenums:0'>
package org.example;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.util.Collections;
import java.util.Map;
import org.eclipse.birt.report.model.api.IResourceLocator;
import org.eclipse.birt.report.model.api.ModuleHandle;
public class StreamResolvingResourceLocator implements IResourceLocator {
@Override
public URL findResource(ModuleHandle module, String filename, int type) {
return findResource(module, filename, type, Collections.emptyMap());
}
@Override
public URL findResource(final ModuleHandle moduleHandle,
final String fileName, final int type,
@SuppressWarnings("
;rawtypes") final Map appContext) {
try {
// The actual URL is not important, it just needs to be valid.
// We will later use the parameters to this method to resolve the
// InputStream.
return new URL(null, "a://b", new URLStreamHandler() {
@Override
protected URLConnection openConnection(URL url)
throws IOException {
return new URLConnection(url) {
@Override
public void connect() throws IOException {
// Connecting may not be needed.
}
@Override
public InputStream getInputStream() throws IOException {
// TODO Return your stream here.
// Do something with fileName for example.
System.out.println("getInputStream called. fileName is: " + fileName);
throw null;
}
};
}
});
} catch (MalformedURLException e) {
// Since it is our own URL, this should not happen.
throw new IllegalStateException(
"Hardcoded URL malformed. Please revisit this class.");
}
}
}
</pre>
<br />
This works for me, I'm on BIRT 4.2.<br />
<br />
You may wish to make separate classes out of the anonymous-inner-class-salad, but I kind of like the terseness.<br />
<br />
I hope this is useful to somebody.
<br />
<br />
Best regards,<br />
Thomas
Tomas.Vala
Hi Thomas,
thanks for your contribution, I am going to give it a try. True it's still somewhat clumsy but still major improvement over my current wasteful workaround using temporary files
Tomas
zimmi
I just noticed that BIRT is caching the returned URLs somewhere and gets confused when the same URL is returned for multiple fileNames.
To resolve this issue, just generate a unique URL for each call with a fileName instead of the static "a://b" thing.
For example by appending the fileName to a protocol, like "birtres://" + fileName.
I use the raw fileName (that is, without all the path information) and append it to a made up protocol.
This seems to work fine.
Tomas.Vala
Good catch. I haven't realized that as I only use this technique to override exactly one Report Library resource all the time.
Tomas