~jstys-z/helioviewer.org/timeline

« back to all changes in this revision

Viewing changes to timeline/Highstock-1.3.10/exporting-server/java/highcharts-export/highcharts-export-web/src/main/java/com/highcharts/export/controller/ExportController.java

  • Committer: Jeff Stys
  • Date: 2014-04-21 12:46:26 UTC
  • Revision ID: jstys@sesda3.com-20140421124626-2332pb2dyjc33jxi
Proof-of-concept version of Data Coverage Timeline using Highchart/Highstock javascript library.  Changes to getDataCoverage API in order to feed the necessary data to the Timeline

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * @license Highcharts JS v2.3.3 (2012-11-02)
 
3
 *
 
4
 * (c) 20012-2014
 
5
 *
 
6
 * Author: Gert Vaartjes
 
7
 *
 
8
 * License: www.highcharts.com/license
 
9
 */
 
10
package com.highcharts.export.controller;
 
11
 
 
12
import java.io.ByteArrayOutputStream;
 
13
import java.io.IOException;
 
14
import java.util.NoSuchElementException;
 
15
import java.util.concurrent.TimeoutException;
 
16
 
 
17
import javax.annotation.Resource;
 
18
import javax.servlet.ServletException;
 
19
import javax.servlet.http.HttpServlet;
 
20
import javax.servlet.http.HttpServletRequest;
 
21
import javax.servlet.http.HttpServletResponse;
 
22
 
 
23
import org.apache.commons.io.IOUtils;
 
24
import org.apache.log4j.Logger;
 
25
import org.springframework.http.HttpStatus;
 
26
import org.springframework.stereotype.Controller;
 
27
import org.springframework.web.bind.annotation.ExceptionHandler;
 
28
import org.springframework.web.bind.annotation.PathVariable;
 
29
import org.springframework.web.bind.annotation.RequestMapping;
 
30
import org.springframework.web.bind.annotation.RequestMethod;
 
31
import org.springframework.web.bind.annotation.RequestParam;
 
32
import org.springframework.web.servlet.ModelAndView;
 
33
 
 
34
import com.highcharts.export.converter.SVGConverter;
 
35
import com.highcharts.export.converter.SVGConverterException;
 
36
import com.highcharts.export.pool.PoolException;
 
37
import com.highcharts.export.util.MimeType;
 
38
import com.highcharts.export.util.TempDir;
 
39
import java.io.File;
 
40
import java.nio.file.Path;
 
41
import java.nio.file.Paths;
 
42
import java.util.logging.Level;
 
43
import javax.servlet.http.HttpSession;
 
44
import org.apache.commons.codec.binary.Base64;
 
45
import org.apache.commons.io.FileUtils;
 
46
import org.apache.commons.io.FilenameUtils;
 
47
import org.apache.commons.lang.RandomStringUtils;
 
48
import org.springframework.http.HttpEntity;
 
49
import org.springframework.http.HttpHeaders;
 
50
 
 
51
@Controller
 
52
@RequestMapping("/")
 
53
public class ExportController extends HttpServlet {
 
54
        private static final long serialVersionUID = 1L;
 
55
        private static final Float MAX_WIDTH = 2000.0F;
 
56
        private static final Float MAX_SCALE = 4.0F;
 
57
        protected static Logger logger = Logger.getLogger("exporter");
 
58
 
 
59
        @Resource(name = "svgConverter")
 
60
        private SVGConverter converter;
 
61
 
 
62
        /* catch all GET requests and redirect those */
 
63
        @RequestMapping(method = RequestMethod.GET)
 
64
        public String getAll(HttpSession session) {
 
65
 
 
66
                String tempFile = (String) session.getAttribute("tempFile");
 
67
                session.removeAttribute("tempFile");
 
68
 
 
69
                if (tempFile != null && !tempFile.isEmpty()) {
 
70
                        // redirect to file download
 
71
                        return "redirect:" + TempDir.getDownloadLink(tempFile);
 
72
                }
 
73
                // redirect to demo page
 
74
                return "redirect:demo";
 
75
        }
 
76
 
 
77
 
 
78
        @RequestMapping(value = "/demo", method = RequestMethod.GET)
 
79
        public String demo() {
 
80
                return "demo";
 
81
        }
 
82
 
 
83
        @RequestMapping(method = RequestMethod.POST)
 
84
        public HttpEntity<byte[]> exporter(
 
85
                @RequestParam(value = "svg", required = false) String svg,
 
86
                @RequestParam(value = "type", required = false) String type,
 
87
                @RequestParam(value = "filename", required = false) String filename,
 
88
                @RequestParam(value = "width", required = false) String width,
 
89
                @RequestParam(value = "scale", required = false) String scale,
 
90
                @RequestParam(value = "options", required = false) String options,
 
91
                @RequestParam(value = "constr", required = false) String constructor,
 
92
                @RequestParam(value = "callback", required = false) String callback,
 
93
                @RequestParam(value = "async", required = false, defaultValue = "false")  Boolean async,
 
94
                HttpServletRequest request,
 
95
                HttpSession session) throws ServletException, InterruptedException, SVGConverterException, NoSuchElementException, PoolException, TimeoutException, IOException {
 
96
 
 
97
                MimeType mime = getMime(type);
 
98
                String tempFilename = null;
 
99
 
 
100
                boolean isAndroid = request.getHeader("user-agent") != null && request.getHeader("user-agent").contains("Android");
 
101
 
 
102
                if (isAndroid || MimeType.PDF.equals(mime) || async) {
 
103
                        tempFilename = createUniqueFileName(mime.name().toLowerCase());
 
104
                }
 
105
 
 
106
                String output = processRequest(svg, mime, width, scale, options, constructor, callback, tempFilename);
 
107
                ByteArrayOutputStream stream;
 
108
 
 
109
                if (async) {
 
110
                        String link = TempDir.getDownloadLink(tempFilename);
 
111
                        // write to stream
 
112
                        stream = new ByteArrayOutputStream();
 
113
                        stream.write(link.getBytes("utf-8"));
 
114
                } else {
 
115
                        stream = ouputToStream(output, mime, tempFilename);
 
116
                }
 
117
 
 
118
                /* If tempFilename is not null, then we want to save the filename in session, in case of GET is used later on*/
 
119
                if (isAndroid) {
 
120
                        session.setAttribute("tempFile", FilenameUtils.getName(tempFilename));
 
121
                }
 
122
 
 
123
                filename = getFilename(filename);
 
124
 
 
125
            HttpHeaders headers = new HttpHeaders();
 
126
                headers.add("Content-Type", mime.getType() + "; charset=utf-8");
 
127
                headers.add("Content-Disposition",
 
128
                   "attachment; filename=" + filename.replace(" ", "_") + "." + mime.name().toLowerCase());
 
129
                headers.setContentLength(stream.size());
 
130
 
 
131
                return new HttpEntity<byte[]>(stream.toByteArray(), headers);
 
132
        }
 
133
 
 
134
        @RequestMapping(value = "/files/{name}.{ext}", method = RequestMethod.GET)
 
135
        public void getFile(@PathVariable("name") String name, @PathVariable("ext") String ext, HttpServletResponse response) throws SVGConverterException, IOException {
 
136
                Path path = Paths.get(TempDir.getOutputDir().toString(), name + "." + ext);
 
137
 
 
138
                ByteArrayOutputStream stream = new ByteArrayOutputStream();
 
139
                try {
 
140
                        stream.write(FileUtils.readFileToByteArray(new File(path.toString())));
 
141
                } catch (IOException ioex) {
 
142
                        logger.error("Tried to read file from filesystem: " + ioex.getMessage());
 
143
                        throw new SVGConverterException("IOException: cannot find your file to download...");
 
144
                }
 
145
 
 
146
                MimeType mime = MimeType.valueOf(ext.toUpperCase());
 
147
 
 
148
                response.reset();
 
149
                response.setCharacterEncoding("utf-8");
 
150
                response.setContentLength(stream.size());
 
151
                response.setContentType(mime.getType());
 
152
                response.setStatus(HttpStatus.OK.value());
 
153
                IOUtils.write(stream.toByteArray(), response.getOutputStream());
 
154
                response.flushBuffer();
 
155
 
 
156
        }
 
157
 
 
158
        @ExceptionHandler(IOException.class)
 
159
        public ModelAndView handleIOException(Exception ex) {
 
160
                ModelAndView modelAndView = new ModelAndView();
 
161
                modelAndView.setViewName("error");
 
162
                modelAndView.addObject("message", ex.getMessage());
 
163
                return modelAndView;
 
164
        }
 
165
 
 
166
        @ExceptionHandler(TimeoutException.class)
 
167
        public ModelAndView handleTimeoutException(Exception ex) {
 
168
                ModelAndView modelAndView = new ModelAndView();
 
169
                modelAndView.setViewName("error");
 
170
                modelAndView
 
171
                                .addObject(
 
172
                                                "message",
 
173
                                                "Timeout converting SVG, is your file this big, or maybe you have a syntax error in the javascript callback?");
 
174
                return modelAndView;
 
175
        }
 
176
 
 
177
        @ExceptionHandler(PoolException.class)
 
178
        public ModelAndView handleServerPoolException(Exception ex) {
 
179
                ModelAndView modelAndView = new ModelAndView();
 
180
                modelAndView.setViewName("error");
 
181
                modelAndView
 
182
                                .addObject(
 
183
                                                "message",
 
184
                                                "Sorry, the server is handling too many requests at the moment. Please try again.");
 
185
                return modelAndView;
 
186
        }
 
187
 
 
188
        @ExceptionHandler(SVGConverterException.class)
 
189
        public ModelAndView handleSVGRasterizeException(Exception ex) {
 
190
                ModelAndView modelAndView = new ModelAndView();
 
191
                modelAndView.setViewName("error");
 
192
                modelAndView
 
193
                                .addObject(
 
194
                                                "message",
 
195
                                                "Something went wrong while converting. " + ex.getMessage());
 
196
                return modelAndView;
 
197
        }
 
198
 
 
199
        @ExceptionHandler(InterruptedException.class)
 
200
        public ModelAndView handleInterruptedException(Exception ex) {
 
201
                ModelAndView modelAndView = new ModelAndView();
 
202
                modelAndView.setViewName("error");
 
203
                modelAndView
 
204
                                .addObject(
 
205
                                                "message",
 
206
                                                "It took too long time to process the options, no SVG is created. Make sure your javascript is correct");
 
207
                return modelAndView;
 
208
        }
 
209
 
 
210
        @ExceptionHandler(ServletException.class)
 
211
        public ModelAndView handleServletException(Exception ex) {
 
212
                ModelAndView modelAndView = new ModelAndView();
 
213
                modelAndView.setViewName("error");
 
214
                modelAndView.addObject("message", ex.getMessage());
 
215
                return modelAndView;
 
216
        }
 
217
 
 
218
        /*
 
219
         * UTILS METHODS
 
220
         */
 
221
 
 
222
        private String processRequest(String svg, MimeType mime, String width, String scale, String options, String constructor, String callback, String filename) throws SVGConverterException, PoolException, NoSuchElementException, TimeoutException, ServletException {
 
223
 
 
224
                Float parsedWidth = widthToFloat(width);
 
225
                Float parsedScale = scaleToFloat(scale);
 
226
                options = sanitize(options);
 
227
                String input;
 
228
                String output;
 
229
 
 
230
                boolean convertSvg = false;
 
231
 
 
232
                if (options != null) {
 
233
                        // create a svg file out of the options
 
234
                        input = options;
 
235
                        callback = sanitize(callback);
 
236
                } else {
 
237
                        // assume SVG conversion
 
238
                        if (svg == null) {
 
239
                                throw new ServletException(
 
240
                                                "The manadatory svg POST parameter is undefined.");
 
241
                        } else {
 
242
                                svg = sanitize(svg);
 
243
                                if (svg == null) {
 
244
                                        throw new ServletException(
 
245
                                                        "The manadatory svg POST parameter is undefined.");
 
246
                                }
 
247
                                convertSvg = true;
 
248
                                input = svg;
 
249
                        }
 
250
                }
 
251
 
 
252
                if (convertSvg && mime.equals(MimeType.SVG)) {
 
253
                                output = converter.redirectSVG(input, filename);
 
254
                } else {
 
255
                        output = converter.convert(input, mime, constructor, callback, parsedWidth, parsedScale, filename);
 
256
                }
 
257
 
 
258
                return output;
 
259
        }
 
260
 
 
261
        private String getFilename(String name) {
 
262
                name = sanitize(name);
 
263
                return (name != null) ? name : "chart";
 
264
        }
 
265
 
 
266
        private static MimeType getMime(String mime) {
 
267
                MimeType type = MimeType.get(mime);
 
268
                if (type != null) {
 
269
                        return type;
 
270
                }
 
271
                return MimeType.PNG;
 
272
        }
 
273
 
 
274
        private static String sanitize(String parameter) {
 
275
                if (parameter != null && !parameter.trim().isEmpty() && !(parameter.compareToIgnoreCase("undefined") == 0)) {
 
276
                        return parameter.trim();
 
277
                }
 
278
                return null;
 
279
        }
 
280
 
 
281
        private static Float widthToFloat(String width) {
 
282
                width = sanitize(width);
 
283
                if (width != null) {
 
284
                        Float parsedWidth = Float.valueOf(width);
 
285
                        if (parsedWidth.compareTo(MAX_WIDTH) > 0) {
 
286
                                return MAX_WIDTH;
 
287
                        }
 
288
                        if (parsedWidth.compareTo(0.0F) > 0) {
 
289
                                return parsedWidth;
 
290
                        }
 
291
                }
 
292
                return null;
 
293
        }
 
294
 
 
295
        private static Float scaleToFloat(String scale) {
 
296
                scale = sanitize(scale);
 
297
                if (scale != null) {
 
298
                        Float parsedScale = Float.valueOf(scale);
 
299
                        if (parsedScale.compareTo(MAX_SCALE) > 0) {
 
300
                                return MAX_SCALE;
 
301
                        } else if (parsedScale.compareTo(0.0F) > 0) {
 
302
                                return parsedScale;
 
303
                        }
 
304
                }
 
305
                return null;
 
306
        }
 
307
 
 
308
        public String createUniqueFileName(String extension) {
 
309
                Path path = Paths.get(TempDir.outputDir.toString(), RandomStringUtils.randomAlphanumeric(8) + "." + extension);
 
310
                return path.toString();
 
311
        }
 
312
 
 
313
        private ByteArrayOutputStream ouputToStream(String output, MimeType mime, String filename) {
 
314
                ByteArrayOutputStream stream = new ByteArrayOutputStream();
 
315
                try {
 
316
                        // for example with PDF files or async download
 
317
                        if (output.equalsIgnoreCase(filename)) {
 
318
                                stream.write(FileUtils.readFileToByteArray(new File(filename)));
 
319
                        }
 
320
 
 
321
                        if (filename == null) {
 
322
                                if (mime.getExtension().equals("svg")) {
 
323
                                        stream.write(output.getBytes());
 
324
                                } else {
 
325
                                        //decode the base64 string
 
326
                                        stream.write(Base64.decodeBase64(output));
 
327
                                }
 
328
                        }
 
329
                } catch (IOException ex) {
 
330
                        java.util.logging.Logger.getLogger(ExportController.class.getName()).log(Level.SEVERE, null, ex);
 
331
                }
 
332
 
 
333
                return stream;
 
334
        }
 
335
 
 
336
}
 
 
b'\\ No newline at end of file'