Java tutorial
/* * Copyright (C) 2012-2013 B3Partners B.V. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ /* Modified: 2014, Eddy Scheper, ARIS B.V. * - A5 and A0 pagesizes added. */ package nl.b3p.viewer.stripes; import java.io.*; import java.net.MalformedURLException; import java.net.URL; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; import javax.servlet.http.HttpServletResponse; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.util.JAXBSource; import javax.xml.transform.Result; import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.sax.SAXResult; import javax.xml.transform.stream.StreamSource; import net.sourceforge.stripes.action.*; import net.sourceforge.stripes.validation.Validate; import nl.b3p.viewer.config.ClobElement; import nl.b3p.viewer.config.app.Application; import nl.b3p.viewer.print.Legend; import nl.b3p.viewer.print.PrintExtraInfo; import nl.b3p.viewer.print.PrintInfo; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.Fop; import org.apache.fop.apps.FopFactory; import org.apache.log4j.Logger; import org.apache.xmlgraphics.util.MimeConstants; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.stripesstuff.stripersist.Stripersist; /** * * @author Roy Braam */ @UrlBinding("/action/print") @StrictBinding public class PrintActionBean implements ActionBean { private static final Log log = LogFactory.getLog(PrintActionBean.class); protected static Logger fopLogger = Logger.getLogger("org.apache.fop"); // 2014, Eddy Scheper, ARIS B.V. - Added. public static final String A5_Landscape = "A5_Landscape.xsl"; // 2014, Eddy Scheper, ARIS B.V. - Added. public static final String A5_Portrait = "A5_Portrait.xsl"; public static final String A4_Landscape = "A4_Landscape.xsl"; public static final String A4_Portrait = "A4_Portrait.xsl"; public static final String A3_Landscape = "A3_Landscape.xsl"; public static final String A3_Portrait = "A3_Portrait.xsl"; // 2014, Eddy Scheper, ARIS B.V. - Added. public static final String A0_Landscape = "A0_Landscape.xsl"; // 2014, Eddy Scheper, ARIS B.V. - Added. public static final String A0_Portrait = "A0_Portrait.xsl"; public static final String DEFAULT_TEMPLATE_PATH = "/WEB-INF/xsl/print/"; // 2014, Eddy Scheper, ARIS B.V. - Added. public static final String A5 = "a5"; public static final String A4 = "a4"; public static final String A3 = "a3"; // 2014, Eddy Scheper, ARIS B.V. - Added. public static final String A0 = "a0"; public static final String LANDSCAPE = "landscape"; public static final String PORTRAIT = "portrait"; public static SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy", new Locale("NL")); @Validate private String params; private ActionBeanContext context; public Resolution print() throws JSONException, Exception { JSONObject jRequest = new JSONObject(params); //get the appId: Long appId = jRequest.optLong("appId"); Application app = Stripersist.getEntityManager().find(Application.class, appId); //get the image url: String imageUrl = getImageUrl(params); //get the form settings final PrintInfo info = new PrintInfo(); if (jRequest.has("title")) { info.setTitle(jRequest.getString("title")); } if (jRequest.has("subtitle")) { info.setSubtitle(jRequest.getString("subtitle")); } info.setDate(df.format(new Date())); info.setImageUrl(imageUrl); if (jRequest.has("bbox")) { info.setBbox(jRequest.getString("bbox")); } if (jRequest.has("overview")) { String url = getOverviewUrl(params); info.setOverviewUrl(url); } if (jRequest.has("extraTekst")) { info.setRemark(jRequest.getString("extraTekst")); } if (jRequest.has("quality")) { info.setQuality(jRequest.getInt("quality")); } /* !!!!temp skip the legend, WIP*/ if (jRequest.has("includeLegend") && jRequest.getBoolean("includeLegend")) { if (jRequest.has("legendUrl")) { JSONArray jarray = null; Object o = jRequest.get("legendUrl"); if (o instanceof JSONArray) { jarray = (JSONArray) o; } else if (o instanceof String) { jarray = new JSONArray(); jarray.put(o); } for (int i = 0; i < jarray.length(); i++) { JSONObject legendJson = new JSONObject(jarray.getString(i)); Legend legend = new Legend(legendJson); info.getLegendUrls().add(legend); } } info.cacheLegendImagesAndReadDimensions(); } if (jRequest.has("angle")) { int angle = jRequest.getInt("angle"); angle = angle % 360; //because the map viewport is rotated the actual map rotation is negative angle = 360 - angle; info.setAngle(angle); } final String mimeType; if (jRequest.has("action") && jRequest.getString("action").equalsIgnoreCase("saveRTF")) { mimeType = MimeConstants.MIME_RTF; } else { mimeType = MimeConstants.MIME_PDF; } // The json structure is: // [{ // class: <String> entry.component.$className, // componentName: <String>entry.component.name, // info: <JSONObject> info in JSONObject // }] if (jRequest.has("extra")) { log.debug("Print Parse 'extra'"); JSONArray jarray = jRequest.getJSONArray("extra"); List<PrintExtraInfo> peis = new ArrayList<PrintExtraInfo>(); for (int i = 0; i < jarray.length(); i++) { JSONObject extraObj = jarray.getJSONObject(i); PrintExtraInfo pei = new PrintExtraInfo(); String className = extraObj.getString("class"); String componentName = extraObj.getString("componentName"); JSONObject infoString = extraObj.getJSONObject("info"); pei.setClassName(className); pei.setComponentName(componentName); pei.setInfoText(infoString); peis.add(pei); } info.setExtra(peis); } //determine the correct template String pageFormat = jRequest.has("pageformat") ? jRequest.getString("pageformat") : A4; String orientation = jRequest.has("orientation") ? jRequest.getString("orientation") : PORTRAIT; final String templateName = getTemplateName(pageFormat, orientation); final String templateUrl; if (app != null && app.getDetails() != null && app.getDetails().get("stylesheetPrint") != null) { //templateUrl=context.getServletContext().getRealPath(DEFAULT_TEMPLATE_PATH+templateName); ClobElement ce = app.getDetails().get("stylesheetPrint"); templateUrl = ce.getValue() + templateName; } else { templateUrl = context.getServletContext().getRealPath(DEFAULT_TEMPLATE_PATH + templateName); } StreamingResolution res = new StreamingResolution(mimeType) { @Override public void stream(HttpServletResponse response) throws Exception { if (templateUrl.toLowerCase().startsWith("http://") || templateUrl.toLowerCase().startsWith("ftp://")) { createOutput(info, mimeType, new URL(templateUrl), true, response); } else { File f = new File(templateUrl); if (!f.exists()) { f = new File(context.getServletContext().getRealPath(templateUrl)); } if (!f.exists()) { log.error("Can't find template: " + f.getAbsolutePath() + ". Using the default templates"); f = new File(context.getServletContext().getRealPath(DEFAULT_TEMPLATE_PATH + templateName)); } try { createOutput(info, mimeType, f, true, response); } finally { info.removeLegendImagesCache(); } } } }; return res; } private void createOutput(PrintInfo info, String mimeType, File xslFile, boolean addJavascript, HttpServletResponse response) throws MalformedURLException, IOException { String path = new File(xslFile.getParent()).toURI().toString(); createOutput(info, mimeType, new FileInputStream(xslFile), path, addJavascript, response); } private void createOutput(PrintInfo info, String mimeType, URL xslUrl, boolean addJavascript, HttpServletResponse response) throws MalformedURLException, IOException { String path = xslUrl.toString().substring(0, xslUrl.toString().lastIndexOf("/") + 1); createOutput(info, mimeType, xslUrl.openStream(), path, addJavascript, response); } /** * Create the output pdf. * @param info the print info * @param mimeType mimeType of the result * @param xslIs inputstream for xsl sheet * @param basePath the base path of that sheet * @param addJavascript addJavascript? * @param response the response for the outputstream * @throws MalformedURLException * @throws IOException */ private void createOutput(PrintInfo info, String mimeType, InputStream xslIs, String basePath, boolean addJavascript, HttpServletResponse response) throws MalformedURLException, IOException { /* Setup fopfactory */ FopFactory fopFactory = FopFactory.newInstance(); /* Set BaseUrl so that fop knows paths to images etc... */ fopFactory.setBaseURL(basePath); /* Setup output stream */ ByteArrayOutputStream out = new ByteArrayOutputStream(); try { /* Construct fop */ FOUserAgent foUserAgent = fopFactory.newFOUserAgent(); foUserAgent.setCreator("Flamingo"); foUserAgent.setProducer("Flamingo"); Date now = new Date(); foUserAgent.setCreationDate(now); foUserAgent.setTitle("Kaart"); Fop fop = fopFactory.newFop(mimeType, foUserAgent, out); //String s=printInfoToString(info); /* Setup Jaxb */ JAXBContext jc = JAXBContext.newInstance(PrintInfo.class); JAXBSource src = new JAXBSource(jc, info); JAXBContext jaxbContext = JAXBContext.newInstance(PrintInfo.class); if (log.isDebugEnabled()) { StringWriter sw = new StringWriter(); jaxbContext.createMarshaller().marshal(info, sw); log.debug("Print XML: " + sw.toString()); } /* Setup xslt */ Source xsltSrc = new StreamSource(xslIs); xsltSrc.setSystemId(basePath); TransformerFactory factory = TransformerFactory.newInstance(); Transformer transformer = factory.newTransformer(xsltSrc); Result res = new SAXResult(fop.getDefaultHandler()); transformer.transform(src, res); /* Setup response */ response.setContentType(mimeType); response.setContentLength(out.size()); /* Set filename and extension */ String filename = "Kaart_" + info.getDate(); if (mimeType.equals(MimeConstants.MIME_PDF)) { filename += ".pdf"; } else if (mimeType.equals(MimeConstants.MIME_RTF)) { filename += ".rtf"; } response.setHeader("Content-Disposition", "attachment; filename=" + filename); //TODO: Postprocess pages to add javascript print /* use postprocessing with itext to add Javascript to output if (addJavascript) { addJsToPdfOutput(out, response); } else { response.getOutputStream().write(out.toByteArray()); }*/ response.getOutputStream().write(out.toByteArray()); response.getOutputStream().flush(); } catch (Exception ex) { log.error("Fout tijdens print output: ", ex); } finally { out.close(); } } private String getOverviewUrl(String params) throws JSONException, Exception { JSONObject info = new JSONObject(params); info.remove("requests"); // Remove old requests, to replace them with overview-only parameters info.remove("geometries"); info.remove("quality"); JSONObject overview = info.getJSONObject("overview"); info.put("bbox", overview.get("extent")); JSONArray reqs = new JSONArray(); JSONObject image = new JSONObject(); image.put("protocol", CombineImageActionBean.IMAGE); image.put("url", overview.get("overviewUrl")); image.put("extent", overview.get("extent")); reqs.put(image); info.put("requests", reqs); String overviewUrl = getImageUrl(info.toString()); return overviewUrl; } /** * Get the image url from the CombineImageAction * @param param the json as string with params needed to create the image * @return url to (combined)image. */ private String getImageUrl(String param) throws Exception { RedirectResolution cia = new RedirectResolution(CombineImageActionBean.class); RedirectResolution pa = new RedirectResolution(PrintActionBean.class); //cia.addParameter("params", param); String url = context.getRequest().getRequestURL().toString(); url = url.replace(pa.getUrl(new Locale("NL")), cia.getUrl(new Locale("NL"))); HttpClient client = new HttpClient(); PostMethod method = null; try { method = new PostMethod(url); method.addParameter("params", param); int statusCode = client.executeMethod(method); if (statusCode != HttpStatus.SC_OK) { throw new Exception("Error connecting to server. HTTP status code: " + statusCode); } JSONObject response = new JSONObject(method.getResponseBodyAsString()); if (!response.getBoolean("success")) { throw new Exception("Error getting image: " + response.getString("error")); } return response.getString("imageUrl"); //return json; } finally { if (method != null) { method.releaseConnection(); } } } // 2014, Eddy Scheper, ARIS B.V. - A5 and A0 added. private String getTemplateName(String pageFormat, String orientation) { if (A5.equalsIgnoreCase(pageFormat) && LANDSCAPE.equalsIgnoreCase(orientation)) { return A5_Landscape; } else if (A5.equalsIgnoreCase(pageFormat) && PORTRAIT.equalsIgnoreCase(orientation)) { return A5_Portrait; } else if (A4.equalsIgnoreCase(pageFormat) && LANDSCAPE.equalsIgnoreCase(orientation)) { return A4_Landscape; } else if (A3.equalsIgnoreCase(pageFormat) && PORTRAIT.equalsIgnoreCase(orientation)) { return A3_Portrait; } else if (A3.equalsIgnoreCase(pageFormat) && LANDSCAPE.equalsIgnoreCase(orientation)) { return A3_Landscape; } else if (A0.equalsIgnoreCase(pageFormat) && PORTRAIT.equalsIgnoreCase(orientation)) { return A0_Portrait; } else if (A0.equalsIgnoreCase(pageFormat) && LANDSCAPE.equalsIgnoreCase(orientation)) { return A0_Landscape; } else { return A4_Portrait; } } //<editor-fold defaultstate="collapsed" desc="Getters and Setters"> public ActionBeanContext getContext() { return context; } public void setContext(ActionBeanContext context) { this.context = context; } public String getParams() { return params; } public void setParams(String params) { this.params = params; } //</editor-fold> private String printInfoToString(PrintInfo info) throws JAXBException { JAXBContext context = JAXBContext.newInstance(PrintInfo.class); Marshaller m = context.createMarshaller(); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); StringWriter sw = new StringWriter(); m.marshal(info, sw); String s = sw.toString(); return s; } }