/* * Copyright 2012 The Solmix Project * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.gnu.org/licenses/ * or see the FSF site: http://www.fsf.org. */ package org.solmix.web.interceptor; import static org.solmix.web.ServletTools.encodeParameter; import java.io.BufferedOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.ServletOutputStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.solmix.api.call.DSCall; import org.solmix.api.call.DSCallWebInterceptor; import org.solmix.api.call.InterceptorOrder; import org.solmix.api.context.WebContext; import org.solmix.api.datasource.DSRequest; import org.solmix.api.datasource.DSRequestData; import org.solmix.api.datasource.DSResponse; import org.solmix.api.datasource.DataSource; import org.solmix.api.exception.SlxException; import org.solmix.api.export.ExportConfig; import org.solmix.api.export.IExport; import org.solmix.api.jaxb.EexportAs; import org.solmix.api.jaxb.Texport; import org.solmix.api.jaxb.Tfield; import org.solmix.api.jaxb.ToperationBinding; import org.solmix.api.jaxb.request.Roperation; import org.solmix.api.types.Texception; import org.solmix.api.types.Tmodule; import org.solmix.commons.util.DataUtils; import org.solmix.fmk.export.ExportManagerImpl; /** * * @author solmix.f@gmail.com * @version $Id$ 2013-12-24 */ public class ExportInterceptor extends DSCallWebInterceptor { private static final Logger LOG = LoggerFactory.getLogger(ExportInterceptor.class); @Override public Action postInspect(DSCall dsCall, WebContext context) throws SlxException { List<DSRequest> requests = dsCall.getRequests(); if (requests != null && !requests.isEmpty()) { if (requests.size() > 1) LOG.warn("DownLoad DSRequest must be single ."); DSRequest req = requests.get(0); if (req.getContext().getIsExport()) { DSResponse res = dsCall.getResponse(req); // put request export relative info to response. ExportConfig config=null; try { config= processExport(req, res); } catch (Exception e1) { throw new SlxException(Tmodule.DSC,Texception.DEFAULT,"collection exportConfiguration error",e1); } // used filter from datasource.if not ,can used res.getSingleResultList(Map.class); List<Map<Object, Object>> data = res.getRecordList(); Map<String, String> fieldMap = new HashMap<String, String>(); DataSource ds = res.getDataSource() == null ? req.getDataSource() : res.getDataSource(); List<String> fieldNames = config.getExportFields(); List<String> finalFields = new ArrayList<String>(); // if no defined export fields used datasource's fields. if (fieldNames == null || fieldNames.isEmpty()) fieldNames = ds.getContext().getFieldNames(); EexportAs exportAs = EexportAs.fromValue(config.getExportAs()); String separatorChar = config.getExportTitleSeparatorChar(); List<String> efields = config.getExportFields(); // loop fieldName. for (int i = 0; i < fieldNames.size(); i++) { String fieldName = fieldNames.get(i); String fieldTitle = null; Tfield field = ds.getContext().getField(fieldName); if (field != null && !field.isHidden() && (field.isCanExport() == null || field.isCanExport())) { fieldTitle = field.getTitle(); if (fieldTitle == null) { fieldTitle = fieldName; } if (exportAs == EexportAs.XML) { if (separatorChar == null) separatorChar = ""; fieldTitle = fieldTitle.replaceAll("[$&<>() ]", separatorChar); } fieldMap.put(fieldName, fieldTitle); finalFields.add(fieldName); } } if (efields == null) { efields = finalFields; } int lineBreakStyleId = 4; if (config.getLineBreakStyle() != null) { String lineBreakStyle = config.getLineBreakStyle().toLowerCase(); lineBreakStyleId = lineBreakStyle.equals("mac") ? 1 : ((int) (lineBreakStyle.equals("unix") ? 2 : ((int) (lineBreakStyle.equals("dos") ? 3 : 4)))); } String delimiter =config.getExportDelimiter(); if (delimiter == null || delimiter == "") delimiter = ","; // get export provider. Map<String, Object> conf = new HashMap<String, Object>(); conf.put(IExport.LINE_BREAK_STYLE, lineBreakStyleId); conf.put(IExport.EXPORT_DELIMITER, delimiter); conf.put(IExport.ORDER, efields); String exportHeader = config.getExportHeader(); if (exportHeader != null) { conf.put(IExport.EXPORT_HEADER_STRING, exportHeader); } String exportFooter = config.getExportFooter(); if (exportFooter != null) { conf.put(IExport.EXPORT_FOOTER_STRING, exportFooter); } IExport export = ExportManagerImpl.get(exportAs, conf); try { ServletOutputStream os = context.getResponse().getOutputStream(); BufferedOutputStream bufferedOS = new BufferedOutputStream(os); String fileNameEncoding = encodeParameter("filename",config.getExportFilename()); if (config.getExportDisplay().equals("download")) { context.getResponse().addHeader("content-disposition", "attachment;" + fileNameEncoding); String contentType = null; switch (exportAs) { case XML: // '\003' contentType = "unknown"; break; case JSON: // '\002' contentType = "application/json"; break; case XLS: // '\004' contentType = "application/vnd.ms-excel"; break; case OOXML: // '\005' contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; break; case CSV: // '\001' contentType = "text/comma-separated-values"; break; default: contentType = "text/csv"; break; } context.setContentType(contentType); } else { context.getResponse().addHeader("content-disposition", (new StringBuilder()).append("inline; ").append(fileNameEncoding).toString()); } export.exportResultSet(data, fieldMap, bufferedOS); // String streamData = writer.toString(); int contentLength = streamData.length(); // context.getResponse().setContentLength(contentLength); bufferedOS.flush(); os.flush(); } catch (IOException e) { throw new SlxException(Tmodule.BASIC, Texception.IO_EXCEPTION, e); } return Action.CANCELLED; } } return Action.CONTINUE; } private ExportConfig processExport(DSRequest dsreq, DSResponse dsresp) throws Exception { DSRequestData reqCtx = dsreq.getContext(); ExportConfig reqconfig = new ExportConfig(); ExportConfig bindconfig = new ExportConfig(); if (reqCtx.getIsExport()) { Roperation rop = reqCtx.getRoperation(); reqconfig.setExportAs(rop.getExportAs()); reqconfig.setExportDelimiter(rop.getExportDelimiter()); reqconfig.setExportDisplay(rop.getExportDisplay()); reqconfig.setExportFilename(rop.getExportFilename()); reqconfig.setExportFooter(rop.getExportFooter()); reqconfig.setExportHeader(rop.getExportHeader()); reqconfig.setExportTitleSeparatorChar(rop.getExportTitleSeparatorChar()); reqconfig.setExportDatesAsFormattedString(rop.getExportDatesAsFormattedString()); reqconfig.setLineBreakStyle(rop.getLineBreakStyle()); String l = rop.getExportFields(); if (l != null) { List<String> fields = new ArrayList<String>(); fields.addAll(DataUtils.simpleSplit(l, ",")); reqconfig.setExportFields(fields); } } ToperationBinding bind = null; try { DataSource ds = dsreq.getDataSource(); if (ds != null) bind = ds.getContext().getOperationBinding(dsreq); } catch (SlxException e) { } if (bind != null) { Texport rop = bind.getExport(); if (rop != null) { bindconfig.setExportAs(rop.getExportAs().value()); bindconfig.setExportDelimiter(rop.getExportDelimiter()); bindconfig.setExportDisplay(rop.getExportDisplay()); bindconfig.setExportFilename(rop.getExportFilename()); bindconfig.setExportFooter(rop.getExportFooter()); bindconfig.setExportHeader(rop.getExportHeader()); bindconfig.setExportTitleSeparatorChar(rop.getExportTitleSeparatorChar()); bindconfig.setLineBreakStyle(rop.getLineBreakStyle()); String l = rop.getExportFields(); if (l != null) { List<String> fields = new ArrayList<String>(); fields.addAll(DataUtils.simpleSplit(l, ",")); bindconfig.setExportFields(fields); } } } DataUtils.copyProperties(reqconfig, bindconfig); return bindconfig; } @Override public PRIORITY priority() { return InterceptorOrder.BEFORE_DEFAULT; } }