001: /*
002: * Copyright 2002-2005 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.web.servlet.view.document;
018:
019: import java.io.OutputStream;
020: import java.util.Locale;
021: import java.util.Map;
022:
023: import javax.servlet.http.HttpServletRequest;
024: import javax.servlet.http.HttpServletResponse;
025:
026: import jxl.Workbook;
027: import jxl.write.WritableWorkbook;
028:
029: import org.springframework.core.io.Resource;
030: import org.springframework.core.io.support.LocalizedResourceHelper;
031: import org.springframework.web.servlet.support.RequestContextUtils;
032: import org.springframework.web.servlet.view.AbstractView;
033:
034: /**
035: * Convenient superclass for Excel document views.
036: *
037: * <p>This class uses the <i>JExcelAPI</i> instead of <i>POI</i>. More
038: * information on <i>JExcelAPI</i> can be found on their <a
039: * href="http://www.andykhan.com/jexcelapi/" target="_blank">website</a>.
040: *
041: * <p>Properties:
042: * <ul>
043: * <li>url (optional): The url of an existing Excel document to pick as a
044: * starting point. It is done without localization part nor the .xls extension.
045: * </ul>
046: *
047: * <p>The file will be searched with locations in the following order:
048: * <ul>
049: * <li>[url]_[language]_[country].xls
050: * <li>[url]_[language].xls
051: * <li>[url].xls
052: * </ul>
053: *
054: * <p>For working with the workbook in the subclass, see <a
055: * href="http://www.andykhan.com/jexcelapi/">Java Excel API site</a>
056: *
057: * <p>As an example, you can try this snippet:
058: *
059: * <pre>
060: * protected void buildExcelDocument(Map model, WritableWorkbook workbook, HttpServletRequest request,
061: * HttpServletResponse response) {
062: * if (workbook.getNumberOfSheets() == 0) {
063: * workbook.createSheet("Spring", 0);
064: * }
065: *
066: * WritableSheet sheet = workbook.getSheet("Spring");
067: * Label label = new Label(0, 0, "This is a nice label");
068: * sheet.addCell(label);
069: * }</pre>
070: *
071: * The use of this view is close to the AbstractExcelView class,
072: * just using the JExcel API instead of the Apache POI API.
073: *
074: * @author Bram Smeets
075: * @author Alef Arendsen
076: * @author Juergen Hoeller
077: * @since 1.2.5
078: * @see AbstractExcelView
079: * @see AbstractPdfView
080: */
081: public abstract class AbstractJExcelView extends AbstractView {
082:
083: /** The content type for an Excel response */
084: private static final String CONTENT_TYPE = "application/vnd.ms-excel";
085:
086: /** The extension to look for existing templates */
087: private static final String EXTENSION = ".xls";
088:
089: /** The url at which the template to use is located */
090: private String url;
091:
092: /**
093: * Default Constructor.
094: * Sets the content type of the view to "application/vnd.ms-excel".
095: */
096: public AbstractJExcelView() {
097: setContentType(CONTENT_TYPE);
098: }
099:
100: /**
101: * Set the URL of the Excel workbook source, without localization part nor extension.
102: */
103: public void setUrl(String url) {
104: this .url = url;
105: }
106:
107: /**
108: * Renders the Excel view, given the specified model.
109: */
110: protected final void renderMergedOutputModel(Map model,
111: HttpServletRequest request, HttpServletResponse response)
112: throws Exception {
113:
114: // Set the content type and get the output stream.
115: response.setContentType(getContentType());
116: OutputStream out = response.getOutputStream();
117:
118: WritableWorkbook workbook;
119: if (this .url != null) {
120: Workbook template = getTemplateSource(this .url, request);
121: workbook = Workbook.createWorkbook(out, template);
122: } else {
123: logger.debug("Creating Excel Workbook from scratch");
124: workbook = Workbook.createWorkbook(out);
125: }
126:
127: buildExcelDocument(model, workbook, request, response);
128:
129: // Should we set the content length here?
130: // response.setContentLength(workbook.getBytes().length);
131:
132: workbook.write();
133: out.flush();
134: workbook.close();
135: }
136:
137: /**
138: * Create the workbook from an existing XLS document.
139: * @param url the URL of the Excel template without localization part nor extension
140: * @param request current HTTP request
141: * @return the template workbook
142: * @throws Exception in case of failure
143: */
144: protected Workbook getTemplateSource(String url,
145: HttpServletRequest request) throws Exception {
146: LocalizedResourceHelper helper = new LocalizedResourceHelper(
147: getApplicationContext());
148: Locale userLocale = RequestContextUtils.getLocale(request);
149: Resource inputFile = helper.findLocalizedResource(url,
150: EXTENSION, userLocale);
151:
152: // Create the Excel document from the source.
153: if (logger.isDebugEnabled()) {
154: logger.debug("Loading Excel workbook from " + inputFile);
155: }
156: return Workbook.getWorkbook(inputFile.getInputStream());
157: }
158:
159: /**
160: * Subclasses must implement this method to create an Excel Workbook
161: * document, given the model.
162: * @param model the model Map
163: * @param workbook the Excel workbook to complete
164: * @param request in case we need locale etc. Shouldn't look at attributes.
165: * @param response in case we need to set cookies. Shouldn't write to it.
166: * @throws Exception in case of failure
167: */
168: protected abstract void buildExcelDocument(Map model,
169: WritableWorkbook workbook, HttpServletRequest request,
170: HttpServletResponse response) throws Exception;
171:
172: }
|