I created a class OnDemandBrowserWindowOpener that subclasses BrowserWindowOpener and otherwise mirrors changes made for our OnDemandFileDownloader (subclasses FileDownloader).
It seems to work, but I wanted to see if any Vaadin experts can tell if the code is useful and correct for our purpose, which is to open up a browser window using dynamic content. So we may send back a PDF or HTML file that is retrieved from our database (and thus has no URL or the like).
And like the other, the key reason is we don’t want to actually fetch the dynamic content unless the button is clicked to trigger it being opened up.
Here’s our code. Feedback is welcome:
public class OnDemandBrowserWindowOpener extends BrowserWindowOpener {
private static final long serialVersionUID = 2448069691276636815L;
/**
* Provide both the {@link StreamSource} and the filename in an on-demand way.
*/
public interface OnDemandStreamSource extends StreamSource {
public String getFilename ();
}
public static class OnDemandStreamResource extends StreamResource {
private static final long serialVersionUID = -1087853524501280897L;
protected HashMap<String,String> parameterMap;
public OnDemandStreamResource(OnDemandStreamSource streamSource) {
super(streamSource,"dummyFileName");
}
public DownloadStream getStream() {
DownloadStream ds = super.getStream();
if ( parameterMap != null ) {
for( String key : parameterMap.keySet() ) {
ds.setParameter(key, parameterMap.get(key));
}
}
// If the cache time is still the default, let's reduce for our dynamic content that shouldn't be cached for a day.
if ( ds.getCacheTime() == DownloadStream.DEFAULT_CACHETIME ) {
ds.setCacheTime(10L * 60L * 1000L); // 10 minutes in msecs
}
return ds;
}
public void setParameterMap(HashMap<String,String> parameterMap) {
this.parameterMap = parameterMap;
}
}
protected final OnDemandStreamSource onDemandStreamSource;
protected HashMap<String,String> parameterMap;
protected Button buttonToEnableWhenDone;
protected String contentType;
protected Integer cacheTime;
public OnDemandBrowserWindowOpener(OnDemandStreamSource onDemandStreamSource) {
super(new OnDemandStreamResource(onDemandStreamSource));
this.onDemandStreamSource = onDemandStreamSource;
}
public OnDemandBrowserWindowOpener(Button buttonToEnableWhenDone, OnDemandStreamSource onDemandStreamSource) {
this(onDemandStreamSource);
this.buttonToEnableWhenDone = buttonToEnableWhenDone;
}
@Override
public boolean handleConnectorRequest(VaadinRequest request, VaadinResponse response, String path) throws IOException {
try {
OnDemandStreamResource sr = getResource();
sr.setFilename( onDemandStreamSource.getFilename() );
if ( contentType != null ) {
sr.setMIMEType(contentType);
}
if ( cacheTime != null ) {
sr.setCacheTime(cacheTime);
}
if ( parameterMap != null ) {
sr.setParameterMap(parameterMap);
}
return super.handleConnectorRequest(request, response, path);
} finally {
if ( buttonToEnableWhenDone != null ) {
buttonToEnableWhenDone.setEnabled(true);
}
}
}
public OnDemandStreamResource getResource() {
return (OnDemandStreamResource)this.getResource(BrowserWindowOpenerState.locationResource);
}
public void setContentType(String v) {
contentType = v;
}
public void setCacheTime(int msecs) {
cacheTime = msecs;
}
public void setStreamSourceParameter(String name, String value) {
if ( parameterMap == null )
parameterMap = new HashMap<String,String>();
parameterMap.put(name, value);
}
}
We then use it something like this:
final Button downloadDocumentSubButton = new Button(label);
downloadDocumentSubButton.setStyleName(Reindeer.BUTTON_LINK);
downloadDocumentSubButton.setDisableOnClick(true);
OnDemandBrowserWindowOpener opener = new OnDemandBrowserWindowOpener(downloadDocumentSubButton, new OnDemandBrowserWindowOpener.OnDemandStreamSource() {
@Override
public InputStream getStream() {
String html = tpd.tpd.getSnapshotDocument(); // this is just how we retrieve the HTML object from the DB
byte downloadHtmlData = EsfString.stringToBytes(html);
return new BufferedInputStream(new ByteArrayInputStream(downloadHtmlData));
}
@Override
public String getFilename() { // currently not working as expected (not shown in the resulting URL)
String htmlFileName;
if ( tpd.tpd.hasDocumentFileName() )
htmlFileName = tpd.tpd.getDocumentFileName();
else {
EsfVaadinUI vaadinUi = EsfVaadinUI.getInstance();
htmlFileName = vaadinUi.getMsg("TranSnapshotPopupButton.document.filename",tpd.documentName,tpd.partyName);
}
return htmlFileName;
}
});
opener.setContentType(Application.CONTENT_TYPE_HTML+Application.CONTENT_TYPE_CHARSET_UTF_8);
opener.setCacheTime(3600000); // 3600 secs (1 hour) in msecs
opener.extend(downloadDocumentSubButton);
layout.addComponent(downloadDocumentSubButton);
The resulting URL in my browser window is:
http://localhost/open-eSignFormsVaadin7/ui/APP/connector/0/245/url/dummyFileName
I’ll need to investigate a bit more, as I wanted it to be the filename I return in my getFileName() method, which is called, but the value clearly doesn’t go through and the default “dummyFileName” is still used.