package er.excel; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.UnsupportedEncodingException; import org.apache.commons.lang3.CharEncoding; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xml.sax.SAXParseException; import com.webobjects.appserver.WOContext; import com.webobjects.appserver.WOResponse; import com.webobjects.foundation.NSData; import com.webobjects.foundation.NSDictionary; import com.webobjects.foundation.NSForwardException; import er.extensions.appserver.ERXResponse; import er.extensions.components.ERXComponentUtilities; import er.extensions.components.ERXNonSynchronizingComponent; /** * Class for Excel Component EGWrapper. * * @binding sample sample binding explanation * * @author ak on Thu Mar 04 2004 */ public class EGWrapper extends ERXNonSynchronizingComponent { /** * Do I need to update serialVersionUID? * See section 5.6 <cite>Type Changes Affecting Serialization</cite> on page 51 of the * <a href="http://java.sun.com/j2se/1.4/pdf/serial-spec.pdf">Java Object Serialization Spec</a> */ private static final long serialVersionUID = 1L; /** logging support */ private static final Logger log = LoggerFactory.getLogger(EGWrapper.class); private String _fileName; private NSDictionary _styles; private NSDictionary _fonts; /** * Public constructor * @param context the context */ public EGWrapper(WOContext context) { super(context); } public boolean isEnabled() { return ERXComponentUtilities.booleanValueForBinding(this, "enabled",false); } public String fileName() { if(_fileName == null) { _fileName = (String)valueForBinding("fileName"); } return _fileName; } public void setFileName(String value) { _fileName = value; } public NSDictionary styles() { if (_styles == null) { _styles = (NSDictionary) valueForBinding("styles"); } return _styles; } public void setStyles(NSDictionary value) { _styles = value; } public NSDictionary fonts() { if (_fonts == null) { _fonts = (NSDictionary) valueForBinding("fonts"); } return _fonts; } public void setFonts(NSDictionary value) { _fonts = value; } @Override public void appendToResponse(WOResponse response, WOContext context) { if (isEnabled()) { ERXResponse newResponse = new ERXResponse(); super.appendToResponse(newResponse, context); String contentString = newResponse.contentString(); contentString = contentString.replaceAll(" ", ""); log.debug("Converting content string:\n{}", contentString); byte[] bytes; try { bytes = contentString.getBytes(CharEncoding.UTF_8); } catch (UnsupportedEncodingException e) { throw new NSForwardException(e, "Can't convert string to UTF-8...you should get a better VM"); } InputStream stream = new ByteArrayInputStream(bytes); EGSimpleTableParser parser = parser(stream); try { NSData data = parser.data(); if((hasBinding("data") && canSetValueForBinding("data")) || (hasBinding("stream") && canSetValueForBinding("stream")) ) { if(hasBinding("data")) { setValueForBinding(data, "data"); } if(hasBinding("stream")) { setValueForBinding(data.stream(), "stream"); } response.appendContentString(contentString); } else { String fileName = fileName(); if(fileName == null) { fileName = defaultFilename(); } response.disableClientCaching(); response.appendHeader(String.valueOf( data.length()), "Content-Length" ); response.setContent(data); // Changed by ishimoto because it was sooooo buggy and didn't work in Japanese response.setHeader("inline; filename=\"" + fileName + "\"", "content-disposition"); response.setHeader(contentType(), "content-type"); } } catch (Exception ex) { if (ex.getCause() instanceof SAXParseException) { SAXParseException parseException = (SAXParseException)ex.getCause(); String logMessage = "'"+context().page().getClass().getName()+"' caused a SAXParseException"; logMessage += "\nMessage: '"+parseException.getMessage()+"'"; // weird but true, getLineNumber is off by 1 (for display purposes I think - mhast) logMessage += "\nLine : "+(parseException.getLineNumber() - 1); logMessage += "\nColumn : "+parseException.getColumnNumber(); logMessage += "\n--- content begin ---"; logMessage += addLineNumbers(contentString); logMessage += "--- content end ---"; log.error(logMessage); throw new NSForwardException(ex); } // else don't handle exception just pass it forward else { throw new NSForwardException(ex); } } } else { super.appendToResponse(response, context); } } protected String addLineNumbers(String in) { String out = ""; int i = 1, beginIndex = 0; int endIndex = in.indexOf('\n'); while (endIndex != -1) { out += in.substring(beginIndex, endIndex+1); beginIndex = endIndex+1; endIndex = in.indexOf('\n', beginIndex); // only want to add line numbers if we have a next newline if (endIndex != -1) out += (i++) + " "; } return out; } protected String defaultFilename() { return "results.xls"; } protected String contentType() { return "application/vnd.ms-excel"; } protected EGSimpleTableParser parser(InputStream stream) { return new EGSimpleTableParser(stream, fonts(), styles()); } }